API Primer - a work in progress

  • 10
  • Idea
  • Updated 9 months ago
I mentioned in a post on another thread that I had done some initial work on an API primer, mainly as a way of corralling my own learning processes as I went along. Various people have expressed an interest in this work, so I have put the current version on my Dropbox here:

https://www.dropbox.com/s/egw5j6u6jc32sj6/A%20Flex%206000%20API%20Primer.pdf?dl=0

I must emphasise that this document is far from complete. If it is useful then I will continue adding the other sections - you can see the outline for the missing bits.

So, budding API developers, does this help? Please let me know.
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
  • A lot of typing coming on

Posted 2 years ago

  • 10
Photo of Bob- W5TX

Bob- W5TX

  • 91 Posts
  • 17 Reply Likes
John
Keep it coming!
Bob, W5TX
Photo of Larry: KE2YC

Larry: KE2YC

  • 66 Posts
  • 5 Reply Likes
John,
Thank you for this!  I am below a novice and this is helping me understand so much more.  The time you are spending is well appreciated.  Keep up the great work you are doing, at some point I may understand fully what I am doing.  HeHe

Tnx John
Larry ke2yc
Photo of Bob G   W1GLV

Bob G W1GLV

  • 654 Posts
  • 109 Reply Likes
John, this has opened my curiosity of the API. Thanks for the document.
Photo of Jim W3IPO

Jim W3IPO

  • 32 Posts
  • 5 Reply Likes
John, I too will now be motivated to dive into the API.  Thanks for sharing---in the true tradition of amateur radio.
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
OK guys, spurred on by your enthusiasm, I spent a disreputable amount of time on this yesterday. The result is, I hope, I reasonable first stab at a complete document, although I am sure more can be added as time and new knowledge permits. Here it is:

https://www.dropbox.com/s/egw5j6u6jc32sj6/A%20Flex%206000%20API%20Primer.pdf?dl=0

I welcome your comments, clarifications, corrections or anything nice you might like to say about it!
Photo of Jim W3IPO

Jim W3IPO

  • 32 Posts
  • 5 Reply Likes
Now 25 pages. Great.
Photo of EA4GLI - 8P9EH - Salvador

EA4GLI - 8P9EH - Salvador

  • 1752 Posts
  • 534 Reply Likes
Thank you very much for this!!!
Photo of Tim - W4TME

Tim - W4TME, Customer Experience Manager

  • 9148 Posts
  • 3467 Reply Likes
You should add this to the API wiki
http://wiki.flexradio.com/index.php?title=Main_Page
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
Hi Tim,

I'm happy to do so but I have no editing rights (I think I did ask a while back but nothing happened). Obviously we need to make it clear that this is not official Flex material, E&OE and so on. Do you propose just adding a link, or actually putting the document itself onto the Wiki?

Might be an idea for Eric or someone else at Flex to cast an eye over it first?
Photo of Tim - W4TME

Tim - W4TME, Customer Experience Manager

  • 9148 Posts
  • 3467 Reply Likes
If you desire editing rights to the wiki, you have to request them.  This is to prevent the wiki from being spammed.

As per the Wiki log in page...

To receive an account that allows editing of wiki articles, contact: devhelp@flexradio.com 

What you are writing is exactly why we used a wiki and not a static website where FlexRadio was entirely responsible fo the content.  If something needs tweaking, we want to wiki contributors to have the ability to modify and add content that helps everyone.

I'd propose sending an e-mail to devhelp and asking if they want to do a content review of your doc.
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
Thanks Tim. I have submitted a request as you suggested.
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
I have added some more content and made a couple of minor corrections to the API Primer. Thanks, as always, to Eric for his invaluable input. Same place... for now:

https://www.dropbox.com/s/egw5j6u6jc32sj6/A%20Flex%206000%20API%20Primer.pdf?dl=0

I'm going to stop now, for the time being at least. I think the Primer has enough information to meet its original objective: to get folks started. If you think there's other stuff that should be in there or you find errors, speeling mistooks or whatever then I'd love to hear from you.
Photo of Kevin K4VD, Elroy

Kevin K4VD, Elroy

  • 775 Posts
  • 171 Reply Likes
This has made for some excellent reading and good prompting to continue working on my programming skills.

In the section, Some Useful Commands, you mention the best way to find the exact syntax for API commands. How do you actually find the API commands? Are they indexed somewhere within the files? 

When the zip file is expanded it creates five folders:
* ComPortPTT
* FlexLib
* UiWpfFramework
* Util
* Vita

I assume by these names that FlexLib contains the actual library code and the rest are tools for specific functions? Within the FlexLib folder I opened FlexLib.csproj in Visual Studio. It opens a bunch of .cs files within the Solutions Explorer. To determine what commands and syntax I can send to the radio I've been going through each file looking for the use of SendCommand. For instance, I see:

SendCommand("transmit set rfpower=" + _rfPower);

To test this, I can set a slider in DXLab Commander to:

~transmit set rfpower=<E3>

and sure enough, it adjusts the RF power. So, to catalog the full API would I simply search out all SendCommand and SendReplyCommand within the files?

Seems there should be a place to go where all the radio commands are documented and annotated but maybe that's too easy.
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
Yes, I'm afraid this is, indeed, too easy. There is a Wiki that holds some promise but it hasn't been updated and is very incomplete. I can understand that the Flex team have limited resources and by far the best use of those resources is to continue developing the product. What that means is the we, as the API programming community need to take more interest in the Wiki and mould it to our needs. Tim has said as much himself.

I believe that Dave AA6YQ has done some work on it and I am hoping to be able to add to it myself in due course. Meanwhile, the FlexLib code seems to be the best form of documentation available to us and that does seem to be kept up to date by Eric and his team. I have not found any catalogue yet, so the search you propose is probably the way to do it.

I am planning to produce a Windows application that will let developers enter commands and see what the responses are. I have most of the code in my controller Mk II project, just need to pull it out into a separate app. A job for the next week or two.
Photo of Kevin K4VD, Elroy

Kevin K4VD, Elroy

  • 775 Posts
  • 171 Reply Likes
Here's a quick extract of all sendcommand and sendreplycommand parameters which I think translate into commands that can be sent to the Flex by a client. I use some of these with DXLabs  Commander user defined controls. The ones marked with an asterisk send data back but I don't think Commander can use that return data. This is all raw stuff but it was a fun exercise. I might try to document these better by filling in the different parameters.

For example, ~audio client 0 slice 0 mute 0 (the tilde is required  by Commander) will mute slice 0. This comes from:

"audio client 0 slice " + _index + " mute " + Convert.ToByte(value)

Is this useful?
AudioStream.cs
 "audio stream 0x" + _rxStreamId.ToString("X") + " slice " + _slice.Index + " gain " + value
 "stream remove 0x" + _rxStreamId.ToString("X")
*"stream create dax=" + _daxChannel

CWX.cs
 "cwx macro save " + (index + 1) + " \"" + msg + "\""
 "cwx send \"" + msg + "\""
 "cwx erase " + num_chars
 "cwx erase " + num_chars + " " + radio_index
 "cwx clear"
 "cwx delay " + _delay
 "cwx wpm " + _speed
*"cwx macro send " + index
*"cwx send \"" + msg + "\" " + block
*"cwx erase " + num_chars + " " + radio_index
*"cwx insert " + radio_index + " \"" + msg + "\" " + block

Equalizer.cs
 "eq " + _eq_select.ToString() + "sc info"
 "eq " + _eq_select.ToString() + "sc mode=" + _eq_enabled.ToString()
 "eq " + _eq_select.ToString() + "sc 32Hz=" + (_level_32Hz).ToString()
 "eq " + _eq_select.ToString() + "sc 63Hz=" + (_level_63Hz).ToString()
 "eq " + _eq_select.ToString() + "sc 125Hz=" + (_level_125Hz).ToString()
 "eq " + _eq_select.ToString() + "sc 250Hz=" + (_level_250Hz).ToString()
 "eq " + _eq_select.ToString() + "sc 500Hz=" + (_level_500Hz).ToString()
 "eq " + _eq_select.ToString() + "sc 1000Hz=" + (_level_1000Hz).ToString()
 "eq " + _eq_select.ToString() + "sc 2000Hz=" + (_level_2000Hz).ToString()
 "eq " + _eq_select.ToString() + "sc 4000Hz=" + (_level_4000Hz).ToString()
 "eq " + _eq_select.ToString() + "sc 8000Hz=" + (_level_8000Hz).ToString()
 "eq " + _eq_select.ToString() + "sc info"
*"eq " + _eq_select.ToString() + "sc info"

IQStream.cs
 "dax iq set " + _daxIQChannel + " rate=" + _sampleRate
 "stream remove 0x" + _streamId.ToString("X")
*"stream create daxiq=" + _daxIQChannel
*"stream create daxiq=" + _daxIQChannel + "ip="+ip.ToString()+" port="+port

Memory.cs
 "memory remove " + _index
 "memory apply " + _index
 "memory set " + _index + " owner=" + _owner.Replace(' ', '\u007f')
 "memory set " + _index + " group=" + _group.Replace(' ', '\u007f')
 "memory set " + _index + " freq=" + StringHelper.DoubleToString(_freq, "f6")
 "memory set " + _index + " name=" + _name.Replace(' ', '\u007f')
 "memory set " + _index + " mode=" + _mode
 "memory set " + _index + " step=" + _step
 "memory set " + _index + " repeater=" + FMTXOffsetDirectionToString(_offsetDirection)
 "memory set " + _index + " repeater_offset=" + StringHelper.DoubleToString(_repeaterOffset, "f6")
 "memory set " + _index + " tone_mode=" + FMToneModeToString(_toneMode)
 "memory set " + _index + " tone_value=" + _toneValue
 "memory set " + _index + " squelch=" + Convert.ToByte(_squelchOn)
 "memory set " + _index + " squelch_level=" + _squelchLevel
 "memory set " + _index + " power=" + _rfPower
 "memory set " + _index + " rx_filter_low=" + _rxFilterLow
 "memory set " + _index + " rx_filter_high=" + _rxFilterHigh
 "memory set " + _index + " rtty_mark=" + _rttyMark
 "memory set " + _index + " rtty_shift=" + _rttyShift
 "memory set " + _index + " digl_offset=" + _diglOffset
 "memory set " + _index + " digu_offset=" + _diguOffset

MICAudioStream.cs
 "stream remove 0x" + _rxStreamId.ToString("X")
*"stream create daxmic"

NetCWStream.cs
 "stream remove 0x" + _txStreamID.ToString("X")
*"stream create netcw"

OpusStream.cs
 "remote_audio rx_on " + Convert.ToByte(_remoteRxOn)
 "stream remove 0x" + _rxStreamId.ToString("X")

Panadapter.cs
 "display pan set 0x" + _stream_id.ToString("X") + " wnb=" + Convert.ToByte(value)
 "display pan set 0x" + _stream_id.ToString("X") + " wnb_level=" + _wnb_level
 "display pan set 0x" + _stream_id.ToString("X") + " rxant=" + _rxant
 "display pan set 0x" + _stream_id.ToString("X") + " rfgain=" + _rfGain
 "display pan set 0x" + _stream_id.ToString("X") + " daxiq=" + _daxIQChannel
 "display pan set 0x" + _stream_id.ToString("X") + " xpixels=" + _width
 "display pan set 0x" + _stream_id.ToString("X") + " ypixels=" + _height
 "display pan set 0x" + _stream_id.ToString("X") + " fps=" + value
 "display pan set 0x" + _stream_id.ToString("X") + " average=" + value
 "display pan set 0x" + _stream_id.ToString("x") + " weighted_average=" + Convert.ToByte(_weightedAverage)
 "display pan set 0x" + _stream_id.ToString("X") + " loopa=" + Convert.ToByte(_loopA)
 "display pan set 0x" + _stream_id.ToString("X") + " loopb=" + Convert.ToByte(_loopB)
 "display pan remove 0x" + _stream_id.ToString("X")
 "slice m " + StringHelper.DoubleToString(clicked_freq_MHz, "f6") + " pan=0x" + _stream_id.ToString("X")
*"display pan create x=" + _width + " y=" + _height
*"display pan rfgain_info 0x" + _stream_id.ToString("X")
*"display pan set 0x" + _stream_id.ToString("X") + " band=" + _band
*"display pan set 0x" + _stream_id.ToString("X") + " center=" + StringHelper.DoubleToString(_centerFreq, "f6")
*"display pan set 0x" + _stream_id.ToString("X") + " bandwidth=" + StringHelper.DoubleToString(new_bw, "f6"
*"display pan set 0x" + _stream_id.ToString("X") + " min_dbm=" + StringHelper.DoubleToString(_lowDbm, "f6")
*"display pan set 0x" + _stream_id.ToString("X") + " max_dbm=" + StringHelper.DoubleToString(_highDbm, "f6")

Radio.cs
 "radio set rtty_mark_default=" + _rttyMarkDefault
 "transmit set show_tx_in_waterfall=" + Convert.ToByte(_showTxInWaterfall)
 "radio set binaural_rx=" + Convert.ToByte(_binauralRX)
 "radio set snap_tune_enabled=" + Convert.ToByte(_snapTune)
 "radio filter_sharpness voice level=" + _filterSharpnessVoice
 "radio filter_sharpness voice auto_level=" + Convert.ToByte(_filterSharpnessVoiceAuto)
 "radio filter_sharpness cw level=" + _filterSharpnessCW
 "radio filter_sharpness cw auto_level=" + Convert.ToByte(_filterSharpnessCWAuto)
 "radio filter_sharpness digital level=" + _filterSharpnessDigital
 "radio filter_sharpness digital auto_level=" + Convert.ToByte(_filterSharpnessDigitalAuto)
 "display panafall create x=100 y=100"
 "cw synccwx " + Convert.ToByte(_syncCWX)
*"client disconnect"
*"ping ms_timestamp=" + _jitterTimer.DurationMsec
*"ping"
*"radio static_net_params ip=" + _staticIP.ToString() + " gateway=" + _staticGateway.ToString() + " netmask=" + _staticNetmask.ToString()
*"radio static_net_params reset"

Slice.cs
 "slice set " + _index + " active=" + Convert.ToByte(_active)
 "slice set " + _index + " rxant=" + _rxant
 "slice set " + _index + " rfgain=" + _rfGain
 "slice set " + _index + " txant=" + _txant
 "slice set " + _index + " mode=" + _demodMode
 "slice unlock " + _index
 "slice set " + _index + " dax=" + _daxChannel
 "filt " + _index + " " + low + " " + high
 "slice set " + _index + " rtty_mark=" + _rttyMark
 "slice set " + _index + " rtty_shift=" + _rttyShift
 "slice set " + _index + " digl_offset=" + _diglOffset
 "slice set " + _index + " digu_offset=" + _diguOffset
 "audio client 0 slice "+ _index + " pan " + _audioPan
 "audio client 0 slice "+ _index + " gain " + _audioGain
 "audio client 0 slice " + _index + " mute " + Convert.ToByte(value)
 "slice set " + _index + " anf=" + Convert.ToByte(value)
 "slice set " + _index + " apf=" + Convert.ToByte(value)
 "slice set " + _index + " anf_level=" + _anf_level
 "slice set " + _index + " apf_level=" + _apf_level
 "slice set " + _index + " diversity=" + Convert.ToByte(value)
 "slice set " + _index + " wnb=" + Convert.ToByte(value)
 "slice set " + _index + " nb=" + Convert.ToByte(value)
 "slice set " + _index + " wnb_level=" + _wnb_level
 "slice set " + _index + " nb_level=" + _nb_level
 "slice set " + _index + " nr=" + Convert.ToByte(_nr_on)
 "slice set " + _index + " nr_level=" + _nr_level
 "slice set " + _index + " agc_mode=" + AGCModeToString(_agc_mode)
 "slice set " + _index + " agc_threshold=" + _agc_threshold
 "slice set " + _index + " agc_off_level=" + _agc_off_level
 "slice set " + _index + " tx=" + Convert.ToByte(_transmit)
 "slice set " + _index + " loopa=" + Convert.ToByte(_loopA)
 "slice set " + _index + " loopb=" + Convert.ToByte(_loopB)
 "slice set " + _index + " rit_on=" + Convert.ToByte(_ritOn)
 "slice set " + _index + " rit_freq=" + _ritFreq
 "slice set " + _index + " xit_on=" + Convert.ToByte(_xitOn)
 "slice set " + _index + " xit_freq=" + _xitFreq
 "slice set " + _index + " step=" + _tuneStep
 "slice set " + _index + "step_list=" ...
 "slice set " + _index + " record=" + Convert.ToByte(_record_on)
 "slice set " + _index + " play=" + Convert.ToByte(_playOn)
 "slice remove " + _index
 "slice waveform_cmd " + _index + " " + s
*"slice create pan=0x" + _panadapter.StreamID.ToString("X")
*"slice create freq=" + StringHelper.DoubleToString(_freq, "f6")
*"slice create rxant=" + _rxant
*"slice create mode=" + _demodMode
*"slice create pan=0x" + _panadapter.StreamID.ToString("X") + " load_from=PERSISTENCE"
*"slice create freq=" + StringHelper.DoubleToString(_freq, "f6") + " load_from=PERSISTENCE"
*"slice create rxant=" + _rxant + " load_from=PERSISTENCE"
*"slice create mode=" + _demodMode + " load_from=PERSISTENCE"
*"slice tune " + _index + " " + StringHelper.DoubleToString(_freq, "f6") +" autopan=0"

TNF.cs
 "tnf set " + _id + " freq=" + StringHelper.DoubleToString(_frequency, "f6")
 "tnf set " + _id + " depth=" + _depth
 "tnf set " + _id + " permanent=" + _permanent
 "tnf set " + _id + " width=" + StringHelper.DoubleToString(_bandwidth, "f6")
 "tnf remove " + _id

TXAudioStream.cs
 "stream remove 0x" + _txStreamID.ToString("X")
*"stream create daxtx"

Waterfall.cs
 "display panafall set 0x" + _stream_id.ToString("X") + " rxant=" + _rxant
 "display panafall set 0x" + _stream_id.ToString("X") + " rfgain=" + _rfGain
 "display panafall set 0x" + _stream_id.ToString("X") + " daxiq=" + _daxIQChannel
 "display panafall set 0x" + _stream_id.ToString("X") + " fps=" + value
 "display panafall set 0x" + _stream_id.ToString("X") + " average=" + value
 "display panafall set 0x" + _stream_id.ToString("x") + " weighted_average=" + Convert.ToByte(_weightedAverage)
 "display panafall set 0x" + _stream_id.ToString("X") + " loopa=" + Convert.ToByte(_loopA)
 "display panafall set 0x" + _stream_id.ToString("X") + " loopb=" + Convert.ToByte(_loopB)
 "display panafall set 0x" + _stream_id.ToString("X") + " line_duration=" + _fallLineDurationMs.ToString()
 "display panafall set 0x" + _stream_id.ToString("X") + " black_level=" + _fallBlackLevel.ToString()
 "display panafall set 0x" + _stream_id.ToString("X") + " color_gain=" + _fallColorGain.ToString()
 "display panafall set 0x" + _stream_id.ToString("X") + " auto_black=" + Convert.ToByte(_autoBlackLevelEnable)
 "display panafall set 0x" + _stream_id.ToString("X") + " gradient_index=" + _fallGradientIndex.ToString()
 "display panafall remove 0x" + _stream_id.ToString("X")
*"display panafall create x=" + _width + " y=" + _height
*"display panafall rfgain_info 0x" + _stream_id.ToString("X")
*"display panafall set 0x" + _stream_id.ToString("X") + " band=" + _band
*"display panafall set 0x" + _stream_id.ToString("X") + " min_dbm=" + StringHelper.DoubleToString(_lowDbm, "f6")
*"display panafall set 0x" + _stream_id.ToString("X") + " max_dbm=" + StringHelper.DoubleToString(_highDbm, "f6"

Xvtr.cs
 "xvtr remove " + _index
 "xvtr set " + _index + " order=" + _order
 "xvtr set " + _index + " name=" + _name
 "xvtr set " + _index + " rf_freq=" + StringHelper.DoubleToString(_rfFreq, "f6")
 "xvtr set " + _index + " if_freq=" + StringHelper.DoubleToString(_ifFreq, "f6")
 "xvtr set " + _index + " lo_error=" + StringHelper.DoubleToString(_loError, "f6")
 "xvtr set " + _index + " rx_gain=" + StringHelper.DoubleToString(_rxGain, "f2")
 "xvtr set " + _index + " rx_only=" + Convert.ToByte(_rxOnly)
 "xvtr set " + _index + " max_power=" + StringHelper.DoubleToString(_maxPower, "f2")
*"xvtr create"
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
Thanks for this Kevin. That sure is a lot of commands!
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
Kevin & John,

I've taken Kevin's list and my own very similar list and tried to understand the sequence and response from the Radio for these commands. I'm continuing to work on it (there are a lot of commands!). I've used my API Tester app (see posting below) to investigate all of this.

Here's a link to dropbox folder containing a spreadsheet (Excel). It has three sheets, the first shows the commands and the responses they generate. I've tried to "name" the responses and you can see the "named" responses listed on the second sheet. The third sheet is a list of all of the Error Codes I've seen so far and an attempt at an explanation for each one.

There are a lot more commands to be added but I'd appreciate any comments. I'm working on a full-fledged GUI client and understanding the sequence/response of the commands is critical to make it work.

There seems to be a difference in the responses to a GUI vs a non-GUI client. I'm not sure I fully understand that at this point. This list, so far, is from the perspective of my non-GUI client (running on my Mac) while the GUI client (SmartSDR) is running on my Windows computer.

https://www.dropbox.com/sh/vyl91c7f85potnt/AACWSiEy_M4XDuvVFaG705Yza?dl=0
Photo of Kevin K4VD, Elroy

Kevin K4VD, Elroy

  • 775 Posts
  • 171 Reply Likes
Very nice work. I'm still just learning C# on Visual Studio so have not gotten as far as creating my own API tester. Is calling the API from different languages that much different? Trying to catch up!

Will this information be posted to the wiki?

73,
Kev K4VD
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
Kevin,

I only have a reading knowledge of C#, I know enough to look through the FlexAPI code and understand roughly what's happening. Learning any language / development environment is a lengthy process. I've been focused on the Mac (Xcode and Swift).

I think the concepts are identical but of course the devil is in the details. In my case (the source is on GitHub) I used a well know open source library (on the Mac) to do the heavy lifting for TCP and UDP handling. If you look at my code there are only  a few dozens of lines of code that I had to write.

Everything I'll publish is certainly free to be used in any way. I'm not exactly sure how something gets included in the Wiki.
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
Eric at FlexRadio has reviewed my API primer and made a number of valuable suggestions for improvements that I have now incorporated into the document. Version 1.002 is available here:

https://www.dropbox.com/s/ocr5wwtxzcq9a9k/A%20Flex%206000%20API%20Primer%20V1-002.pdf?dl=0

Many thanks, Eric!

Edit: I've also added a link to the FlexRadio Wiki
(Edited)
Photo of Kevin K4VD, Elroy

Kevin K4VD, Elroy

  • 775 Posts
  • 171 Reply Likes
"It is perhaps unreasonable to expect FlexRadio to maintain this when it should be using its resources on developing products. I would argue that it is up to the API programming community to put some
effort into providing the documentation it needs."

Not sure I fully agree with this or maybe I'm not appreciating the intention of the statement. The API comes from Flex and the maintainer of the API should document their work. Being an API intended for others to interface with the Flex radio the source of the API should also be the major contributor to API documentation. This shows a commitment to the API and, potentially, a clue to the API's stability so that others can feel confident developing new products using this API. Look at the Google Chrome extension ecosystem. None of it would be possible without active maintenance and contribution from the core Google Chrome development team.

I suggest official and maintained documentation is at least as important as pushing out new features. I also believe that if Flex courts third party developers (professional and maker) with a well documented API both Flex and its customers will benefit.
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
This is a great idea, I wish I had this document when I started trying to write code to talk to my Flex (6500). Having spent a good deal of time trying to puzzle out the kind of things in your document, I can appreciate how difficult this information is to come by. I'll make a point to read through and offer up any information I may have gleaned that isn't already in the document.

One area that continues to puzzle me is the error message code that sometimes comes in a command reply (see page 13 of your document). An example is as follows:

I send -->c1|client program|myProgramName<--

I and receive back -->r1|10000002|unknown client program<--

I understand the text but how do I parse the 10000002  to make sense of it?

Similarly I send -->c2|client gui<--

And I receive back -->r2|50001000

What does 50001000 mean?

Please keep up the great work. Let the rest of us know how we can contribute.

73's Doug, K3TZR 
Photo of Steve - N5AC

Steve - N5AC, VP Engineering / CTO

  • 1030 Posts
  • 999 Reply Likes
You should be able to place a "D" before your command to enable debugging and get a more detailed answer.  For example "DC1|client gui".  In this particular case, 0x50001000 is SL_RESP_UNKNOWN which means that the command code that processed this command did not respond with a valid response.  It essentially means that you are in limbo because neither a success nor an error were passed back to the command processor.  I generally would like to know when you see these so we can go fix the code that produces an error like this.

The CD1| should give you an answer like "Command result unknown"
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
Steve, thanks for the reply. Please note that my first description of the issue contains errors, only my second posting is correct.

The "C1|client gui" command sends back "r1|10000002|unknown client program" even without a "D" in the command.

The "C16|sub tnf all" command sends back "r16|50001000" whether I send a "CD16" or "C16" (I tried both upper and lower case, it doesn't seem to matter).

In fact there are no TNF's on the radio at the time I send the command but I wouldn't expect that to cause a non-zero response value for a "sub tnf all" command.

It would be helpful if there were some list of error codes and/or some explanation for how to parse the codes.

Thanks again for your help.
Photo of Steve - N5AC

Steve - N5AC, VP Engineering / CTO

  • 1030 Posts
  • 999 Reply Likes
OK very good thanks for more info.  I think if you retry the command you will see that can only get a successful response from "client gui".  This command cannot respond with the error you are listing.  Client GUI tells the radio that your client will be the only gui client and should be sent all displays.  I have added the client gui command to the wiki here:

http://wiki.flexradio.com/index.php?title=TCP/IP_client

This page does have the error you mention (unknown client program) but it is a response to the client program command.  As it notes at the bottom, this is not an error (hence the 1 at the start of the hex value), it is informational and states that the radio has no prior knowledge nor info about your program.  Some programs have specific behaviors programmed in the radio.

I've added the C defines file for the constants used in the SmartSDR API here:

http://wiki.flexradio.com/index.php?title=Known_API_Responses 
Photo of Steve - N5AC

Steve - N5AC, VP Engineering / CTO

  • 1030 Posts
  • 999 Reply Likes
Also you "sub tnf" question sparked my interest so I went and looked -- the TNF status messages are delivered on object_radio which means that you have to subscribe to the radio, not TNFs.  I'm not certain why there is not a separate TNF subscription from the radio subscription off the top of my head, but this is how it is currently implemented.  
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
Thanks for the update, I removed "sub tnf all" and replaced it with "sub radio all"; no errors were reported back on that command.

I don't have TNF's fully implemented yet so I'm not sure whether I'm receiving the TNF data as a result of this subscription. I should know in a few days.
Photo of Fred GLENN

Fred GLENN

  • 54 Posts
  • 7 Reply Likes
John, after stumbling through the API myself just to read the frequency data, I can appreciate your efforts. Thanks SO MUCH for doing this. I'm still learning from it.

Fred, K9SO
Photo of Dave AA6YQ

Dave AA6YQ

  • 93 Posts
  • 54 Reply Likes
Re " I can understand that the Flex team have limited resources and by far the best use of those resources is to continue developing the product."

An ecosystem populated by attractive complementary products requires a functional, well-documented API. Such ecosystems can be powerful differentiators and force multipliers, attracting the innovation and productivity of many more developers than the core team can afford to pay or orchestrate. A thriving ecosystem can also provide a steady stream of acquisition candidates.

The Flex API Wiki is usable, but full of gaps; while Flex personnel have been very responsive to questions created by those gaps, comprehensive descriptions of all functions and illustrative examples are needed to attract broad interest from the amateur developer community.
(Edited)
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
Hi Dave, long time no see!

I entirely agree with you. In an ideal world the API would be fully documented and we wouldn't have to delve into the FlexLib API code. I know you've done a lot of work on the Wiki, which is great. I found it hard work finding enough information to get started, so my primer is an attempt to help others at that early stage. A bit of self help from within the community is no bad thing.
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
As John (G3WGV) mentions in his API Primer, once you get started working on any sort of Flex Radio Client, you'll need to be able to explore the FlexAPI. A good way to do that is, as John also suggests, to build a small program to experiment with API comments. I've taken his advice and built such a program for use on a Mac. If anyone is interested, I can put the source code on Dropbox and/or GitHub. With a little work, I can also create a DMG.

Here's a snapshot of the program taken just after I pressed the connect button showing the replies from the Radio as a result of establishing a TCP connection to it.



and here after sending it an "info" command (sent commands in green, replies in red):

Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
Hi Doug,

That's an excellent piece of work, well done!

I have been working on a very similar program for Windows and am also willing to make both the source code and the executable available if people are interested. The code is written in Delphi XE7, using the INDY 10.6 internet component suite.

Underlying the test harness application is my Flex API helper code, which is now nearly fully developed. This code provides broadly the same "middleware" capabilities as the FlexLib API but in a Delphi XE environment. This code is also available to anyone who might want it.

Here's a screen shot just after connection & slice subscription.

Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
Hi John,

Thanks for the reply. I've put my source code on GitHub

(https://github.com/DougPA/FlexAPITester/tree/master/FlexAPITester)

I can supply an executable as well. It's written in Swift 3 using the GCDAsyncSocket (Objective-C) library. 

Now we need to put theses things to use and enhance your already very good API Primer. I've been tinkering with this for some time now and the lack of information about commands, their usage and their timing has made things difficult.

Like you, I've written code to perform the same functionality as FlexAPI. In my case because I couldn't run FlexAPI on a Mac. I'm in the process of testing a Mac client (i.e. a Mac version of SmartSDR). It's far from complete but so far I'm only trying to confirm that my FlexAPI implementation is complete and capable of supporting a client. I'll put the API code on GitHub as soon as I've tested it adequately.

Some of the code for the API Tester was "borrowed" from my FlexAPI implementation so its part of testing my work. I've implemented all of the Discovery, TCP and UDP aspects of the FlexAPI but didn't choose to put Discovery and UDP into the Tester, maybe the next version.

As I learn things I'll send you information that you may want to incorporate into your API Primer.

Thanks for starting this.

73's Doug
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
Here's an update to my Flex API Commands spreadsheet. I've learned a lot in the last few days and the spreadsheet has changed considerably. If you have the previous one, throw it away and use this one. I'll update it as I learn more. The name will include the date of last update so it should be easy to see if there's anything new.

Be sure to look at the first sheet in the spreadsheet. It's a short explanation of all the other sheets.

https://www.dropbox.com/sh/vyl91c7f85potnt/AACWSiEy_M4XDuvVFaG705Yza?dl=0

I've also updated/corrected the FlexAPITester and put the updated source on GitHub.
(Edited)
Photo of Mike Burns, AB1LD

Mike Burns, AB1LD

  • 14 Posts
  • 3 Reply Likes
Hi Doug,

Nice work on the API. I'm developing an interface in Mathematica, which is not ideal for real-time ethernet processing (but is wonderful for processing data). Your spreadsheet has been invaluable in this process (as is John's Primer). I've been exploring the API using Terminal on my mac but that is a tedious process.

It would be great if you could put up the executable of your swift program. Its been a long time since I've used Xcode and I've only been lightly following swift (too many languages in the world!) so it would take me a while to get it going from your GitHub source. If its not too much trouble to put up an executable that would be much appreciated.

Thanks,
Mike - AB1LD
Photo of Mike Burns, AB1LD

Mike Burns, AB1LD

  • 14 Posts
  • 3 Reply Likes
Doug,

The class IDs that I check for are 0x02e3, 0x02e4, 0x02e5 and 0x02e6.
Its always possible that you may have picked off the "2" in how you access the data. The python program I use does some fancy bit selection when its checking packet information.

Mike
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
You're absolutely correct, I'm looking at it now and it seems that I'm expecting 0x00e3 but getting 0x02e3 for the packet class code for daxiq24. Do you know which is correct. Sometime (in the murky past) I put together the enum for packet class code and have the value 0x00e3. Here's a list of the enum:

        case meter = 0x8002

        case panadapter = 0x8003

        case waterfall = 0x8004

        case opus = 0x8005

        case daxIq24 = 0x00e3

        case daxIq48 = 0x00e4

        case daxIq96 = 0x00e5

        case daxIq192 = 0x00e6

        case daxAudio = 0x03e3

        case discovery = 0xffff

I know that meter, panadapter, waterfall and opus are correct because I have them all working.
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
OK, I changed the packet class codes to have the "2".

Are the daxIq packets class type IFDataWithStream?, I had assumed (bad idea) that they were ExtDataWithSTream.
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
To answer my own question, I think they are IfDataWithStream.

I'll make the appropriate changes and put out a new source and executable in a few hours after I do some more checking.

BTW, I think I'll also make the SEND button clear the Command field (after the command is sent), it seems tedious to have to clear it manually each time.

Thanks very much for your help in correcting my mistakes. One of the big benefits of sharing the code / app is feedback like this.
(Edited)
Photo of Mike Burns, AB1LD

Mike Burns, AB1LD

  • 14 Posts
  • 3 Reply Likes
Delighted to make my contribution. I'll be putting up my code in the near future.
Photo of Kevin K4VD, Elroy

Kevin K4VD, Elroy

  • 775 Posts
  • 171 Reply Likes
John:

In the API document you show the following table for scaling meter readings:


I captured SWR, forward and reflected power via the API. It looks like SWR has no scaling. For forward and reflected power I had to use this formula found in the Gary's fqapsac code that seems to return the correct result:

double myData = Math.Pow(10.0, (data / 10)) / 1000;

With RF Power set to 5 I got the following readings:

forward power: 36.45313 translates to 4.4 watts
reflected power: 18.70313 translates to 0.074 watts
SWR: 1.210938 calculated from above it's 1.3:1

Could the reason for the difference in scaling be where we are getting our data from? I'm using flexlib which might be doing some scaling already. I need to check that.

I finally figured out how to discover, connect and collect some data with the help of Mark WS7M and his videos. The conversion above came from Gary Robinson's fqapsac code along with a whole buch of other neat stuff. After a night's work I have a little hello world app that presents froward and reflected power and swr. Radio was set to 36 on the RF Power slider.



There's definitely a whole lot more to this stuff than I expected. I think I learned 12 new terms today and only had to unlearn 5 I thought I knew. Not a bad day.

73,
Kev K4VD
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
Hi Kev,

Not quite. My primer is on the radio API itself. FlexLib is a structured interface between the API and an application. It handles many of the details of the API, on behalf of the application, making the application much simpler to code. Doing the scaling to correctly represent meter values as a floating point value is but one example. The API.Init() and Connect() functions you mention are similar examples - there is quite a lot involved at an API level in that Connect() function!

For no other reason than that I wanted to, I have, in effect, written my own FlexLib. That meant I had to grapple with the raw API and it was from that epic struggle that my API primer emerged :-)

Good luck with your programming. It can be extremely rewarding and outrageously frustrating in equal measure but there is something very satisfying in using code that you wrote to make QSOs. It's another sort of construction project really.

73, John.
Photo of Kevin K4VD, Elroy

Kevin K4VD, Elroy

  • 775 Posts
  • 171 Reply Likes
Gotcha. I'm starting to see how the pieces fall together.

And I agree, it seems programming is a new aspect of homebrewing for me. I realize I'm having a good time after something finally works. Until then, I'm pulling my hair out trying to figure out if I'm misunderstanding the API, the library, the code, the language or the development environment! I've gotten a lot of help from the community though so I'm in real good shape I think.

Kev
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
Earlier I wrote:
I notice that the page has been changed recently to show the volts/amps scaling factor as 256 but as far as I can see that is wrong. I am investigating.
Word from the coalface is that the meter scaling will be changing in a future release. At the moment it is still as per my API primer.

This must be one of those rare occasions where the documentation gets ahead of the code!
(Edited)
Photo of Michael DK6JU

Michael DK6JU

  • 1 Post
  • 0 Reply Likes
John, where can i find your API primer now? All the dropbox-links do not work (error 404).
Photo of John G3WGV

John G3WGV

  • 187 Posts
  • 35 Reply Likes
HI Michael,

I don't know where you are looking but the link from the API Wiki, at http://wiki.flexradio.com/index.php?title=Main_Page works fine for me and that is the only place where I plan to maintain a link.

I need to review the Primer! There have been some changes since I last edited it.

73, John, G3WGV
Photo of Mark - WS7M

Mark - WS7M

  • 994 Posts
  • 354 Reply Likes
The API Primer is wonderful.  It covers much of what I had to learn by experimentation.  I will try if you are willing to add to it where I can.  I'll send you snippets of stuff I've learned.

To all here who are programming I'm willing to help in anyway I can.  I have helped a few on here solve issues with programs they were writing.  It helps me to help you.

I'm a device programmer by trade.  Been making PC's talk to things and control them for over 30 years.  Been a ham since roughly 1972.  This radio and the ability to program it brings two things together for me so if I can help spread the love I will.

Mark - WS7M
Photo of Kevin K4VD, Elroy

Kevin K4VD, Elroy

  • 775 Posts
  • 171 Reply Likes
To all that are interested, Mark has given me enough offline guidance where I've become much more comfortable both with the radio's API and with the programming environment I'm using. I basically started with no clue and learning about for loops and variables from a book to making a connection to the radio, reading meters and presenting them in a window after viewing Mark's two videos and getting some help by email. I still have a lot of questions but I'm slowly working through them.

Thanks Mark.

73,
Kev K4VD
Photo of Ken - NM9P

Ken - NM9P, Elmer

  • 3971 Posts
  • 1226 Reply Likes
Are you programming in C# ? I have been meaning to get started learning that so I can port the DJ MIDI program from "Processing" to C#. But I got sidetracked along the way.

This discussion it piquing my interest again!

Ken - NM9P
Photo of Kevin K4VD, Elroy

Kevin K4VD, Elroy

  • 775 Posts
  • 171 Reply Likes
Hi Ken... Yes I am. I'm dividing my time between a C# getting started book, Mark's videos and tutorials and Gary's code (way above my head right now). I'm using Visual Studio 2015 Community... free and fun.

Kev
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
Does anyone know if you can change a meter's "fps" (frames per second)? For example is there a command like:

c<seqnum> | meter 5 fps=1

Which would set meter #5 to one frame per second.

It seems like there should be but when I send it I get back a reply with the 50001000 message (basically, it doesn't know what I mean). I'm monitoring the "+13.8B" and "PATEMP" meters and it seems a waste to have them set to 10 frames per second.
Photo of Steve - N5AC

Steve - N5AC, VP Engineering / CTO

  • 1030 Posts
  • 999 Reply Likes
Today there is no command to change the meter rate.  The interval used to send the meter is stored with the meters already in the radio as a data item and we could easily create a command to change these values, but it's not there toady.  The meters are sent whenever a meter quantum is reached and meters are ready.  For example, if the quantum is 30ms and the meter is a 50ms meter, then at quantum 0, the meter will not be included in the meter packet.  At quantum 2, the meter will be ready and will be sent.
Photo of Doug - K3TZR

Doug - K3TZR

  • 93 Posts
  • 11 Reply Likes
Thanks Steve, it's not terribly important, I just thought I had read it somewhere and when I tried it, it didn't work.