Welcome to the new FlexRadio Community! Please review the new Community Rules and other important new Community information on the Message Board.
If you are having a problem, please check the Help Center for known solutions.
Need technical support from FlexRadio? It's as simple as Creating a HelpDesk ticket.

API Primer - a work in progress

John G3WGVJohn G3WGV Member ✭✭
edited June 23 in New Ideas
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.
9 votes

Open for Comments · Last Updated

«13

Comments

  • Bob- W5TXBob- W5TX Member ✭✭
    edited May 2017
    John Keep it coming! Bob, W5TX
  • Larry: KE2YCLarry: KE2YC Member ✭✭
    edited August 2019
    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
  • Bob G   W1GLVBob G W1GLV Member ✭✭
    edited June 16
    John, this has opened my curiosity of the API. Thanks for the document.
  • Jim W3IPOJim W3IPO Member ✭✭
    edited February 2019
    John, I too will now be motivated to dive into the API.  Thanks for sharing---in the true tradition of amateur radio.
  • John G3WGVJohn G3WGV Member ✭✭
    edited November 2018
    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!
  • Jim W3IPOJim W3IPO Member ✭✭
    edited February 2019
    Now 25 pages. Great.
  • EA4GLIEA4GLI Salvador Member ✭✭
    edited November 2016
    Thank you very much for this!!!
  • Tim - W4TMETim - W4TME Administrator, FlexRadio Employee admin
    edited March 2017
    You should add this to the API wiki
    http://wiki.flexradio.com/index.php?title=Main_Page
  • John G3WGVJohn G3WGV Member ✭✭
    edited November 2018
    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?
  • Tim - W4TMETim - W4TME Administrator, FlexRadio Employee admin
    edited December 2016
    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: [email protected] 

    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.
  • John G3WGVJohn G3WGV Member ✭✭
    edited December 2016
    Thanks Tim. I have submitted a request as you suggested.
  • John G3WGVJohn G3WGV Member ✭✭
    edited July 2019
    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.
  • KevinKevin Member
    edited December 2016
    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.


  • John G3WGVJohn G3WGV Member ✭✭
    edited December 2016
    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.
  • KevinKevin Member
    edited July 2019
    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"
  • John G3WGVJohn G3WGV Member ✭✭
    edited July 2019
    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
  • John G3WGVJohn G3WGV Member ✭✭
    edited December 2016
    Thanks for this Kevin. That sure is a lot of commands!
  • KevinKevin Member
    edited January 2017
    "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.


  • Doug - K3TZRDoug - K3TZR Member
    edited July 2019
    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 
  • KevinKevin Member
    edited December 2016
    Some of this information you can find on the wiki at <http://wiki.flexradio.com/index.php?title=TCP/IP_client>. Unfortunately not all the return codes are provided.


  • Doug - K3TZRDoug - K3TZR Member
    edited November 2016
    Thanks Kevin, I had looked there a long time ago, apparently it has been updated a bit. One of the things the "Message Format" says is that bit 24-25 are the severity.

    If I look at the 500001000 reply, that would be 0x1dcd68e8 which would make bits 24-25 (assuming counting from lsb) 0x01 meaning "Warning", but there isn't much explanation other than that.

    Also the 10000002 reply (0x989682) has bits 24-25 as 0x00 which would be "Informational", that makes sense but I still don't know what the other bits represent.

    Maybe we can persuade Flex to do an API technical presentation at one of the hamfests (Dayton?).
  • Doug - K3TZRDoug - K3TZR Member
    edited November 2016
    It turns out that I had a bug in my code logging the replies to commands. Now that I've corrected that I still see two commands that generate non-zero replies:

    "client gui" sends back r1|10000002|unknown client program

    "sub tnf all" sends back r16|50001000

    From the guidance on the wiki I've figured out/guessed that the reply values are actually hex strings. Treating them that way, these both will have bits 24-25 as zero and are therefore "informational". The significance of the rest of the bits is still unknown to me. The wiki also says that a reply with the leftmost digit a one is "informational".
  • Steve-N5ACSteve-N5AC Community Manager admin
    edited December 2016
    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"
  • Doug - K3TZRDoug - K3TZR Member
    edited December 2016
    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.
  • K9SOK9SO Member ✭✭
    edited January 2019
    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
  • Steve-N5ACSteve-N5AC Community Manager admin
    edited December 2016
    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 
  • Steve-N5ACSteve-N5AC Community Manager admin
    edited December 2016
    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.  
  • Doug - K3TZRDoug - K3TZR Member
    edited December 2016
    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.
  • Dave AA6YQDave AA6YQ amateur radio software developer (DXLab) Member ✭✭
    edited September 2019
    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.
  • John G3WGVJohn G3WGV Member ✭✭
    edited December 2016
    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.

Leave a Comment

Rich Text Editor. To edit a paragraph's style, hit tab to get to the paragraph menu. From there you will be able to pick one style. Nothing defaults to paragraph. An inline formatting menu will show up when you select text. Hit tab to get into that menu. Some elements, such as rich link embeds, images, loading indicators, and error messages may get inserted into the editor. You may navigate to these using the arrow keys inside of the editor and delete them with the delete or backspace key.