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 refer to the product documentation or check the Help Center for known solutions.
Need technical support from FlexRadio? It's as simple as Creating a HelpDesk ticket.

SmartSDR TCP/IP API - Starting demodulation and receiver using telnet

IW7DMH, Enzo
IW7DMH, Enzo Member ✭✭
Hello,

my studies about TCP/IP API are going on, and now I can easily connect my Flex 6300 and tune  the slice (using something like C12|slice t 0 14.035).
Everything works fine if SSDR is already running, but now I want to go over: I would like to start the receiver when SSDR (and all its related software) is off.
When SSDR is turned off my client can still connect the rig and tune the slice but I can't hear anything.
To start the receiver I have to remove the slice and its pan (C22|slice r 0 - C23|display pan r 0x40000000) and then create them from scratch (C24|display pan c 14.008000 1 800 400 - C25|slice c 14.009 1 cw). At this point the receiver magically starts.
I am wondering if there is another way to start the receiver using the slice that is already created after the connection.
Sure I am missing something, can you help me?

Thanks you very much
73' Enzo
iw7dmh

Answers

  • Stu Phillips - K6TU
    Stu Phillips - K6TU Member ✭✭
    edited May 2020
    Enzo,

    You don't have to create a pan adaptor before creating a slice...
    c2|sub slice all
    R2|0|
    c3|slice c 14.185 ant1 usb
    R3|0|0
    S22347252|slice 0 mode_list=LSB,USB,AM,CW,DIGL,DIGU,SAM,FM,NFM,DFM
    S22347252|slice 0 pan=0x00000000 mode=USB qsk=0 tx=1
    S22347252|interlock timeout=0 acc_txreq_enable=0 rca_txreq_enable=0 acc_txreq_polarity=0 rca_txreq_polarity=0 tx1_enabled=1 tx1_delay=0 tx2_enabled=1 tx2_delay=0 tx3_enabled=1 tx3_delay=0 acc_tx_enabled=1 acc_tx_delay=0 tx_delay=20
    S22347252|radio slices=7 panadapters=7 lineout_gain=60 lineout_mute=0 headphone_gain=50 headphone_mute=0 remote_on_enabled=1 pll_done=0 freq_error_ppb=0 cal_freq=15.000 tnf_enabled=1 snap_tune_enabled=1 nickname=K6TU-007 callsign=K6TU
    S22347252|slice 0 in_use=1 RF_frequency=14.185000 rit_on=0 rit_freq=0 xit_on=0 xit_freq=0 rxant=ANT1 mode=USB wide=0 filter_lo=100 filter_hi=2800 step=10 step_list=1,10,50,100,500,1000,2000,3000 agc_mode=med agc_threshold=65 agc_off_level=10 pan=0x00000000 txant=ANT1 loopa=0 loopb=0 qsk=0 dax=0 dax_clients=0 lock=0 tx=1 dax_tx=0 active=1 audio_gain=50 audio_pan=50 audio_mute=0 record=0 play=disabled record_time=0.0 anf=0 anf_level=50 nr=0 nr_level=50 nb=0 nb_level=50 apf=0 apf_level=0 squelch=0 squelch_level=0 diversity=0 diversity_parent=0 diversity_child=0 diversity_index=1342177293 ant_list=ANT1,ANT2,RX_A,RX_B,XVTR mode_list=LSB,USB,AM,CW,DIGL,DIGU,SAM,FM,NFM,DFM fm_tone_mode=OFF fm_tone_value=67.0 fm_repeater_offset_freq=0.000000 tx_offset_freq=0.000000 repeater_offset_dir=SIMPLEX
    S0|interlock state=READY reason= source=
    S0|interlock tx_allowed=1
    Just create the slice and the audio stream begins from the radio.

    Note that you do need to provide the antenna port for the slice as a string compatible with the create slice command.  These are show in ant_list under the slice information.


    Stu K6TU
  • IW7DMH, Enzo
    IW7DMH, Enzo Member ✭✭
    edited January 2017
    Thank you very much Stu,

    about the antenna ID I was mislead from wiki docs, it reports the command "slice c" with the antenna ID and not with the antenna name, but in my Wireshark logs I have the correct command.
    Sorry for my mistake.

    If I can, I would tell you about other doubts:

    1- just after the connection (when SSDR is off) the command "sub slice all" give me an already created slice (sorry for my poor english); I think the Flex restore it from its previous saved state. In theory, at this point, I should already have to listen to the radio but it doesn't happen.

    Actually for me is not clear what really happens when the rig is just turned on and the "first" client connects to it. It should be helpful trying to define a correct sequence diagram.

    2- the second doubt is also related to the above question: what is the correct way to disconnect from a Flex 6000? I noted that when SSDR is turned off my client receive some S0| status packets.

    3- does the Flex save the status for each connected client? It could recognize the client from the name passed with the command "client program <name>". Or do I have to use the "client start_persistence " command?

    73' Enzo IW7DMH
  • Stu Phillips - K6TU
    Stu Phillips - K6TU Member ✭✭
    edited May 2020
    Enzo,

    Comments on your questions (and of course, some of my own!).

    1. What version of software are you running?  I am currently testing an alpha release but I don't see the behavior you describe.  When I issue the command "sub slice all" on a radio, there is no active slice and the radio status shows 8 available slices and 8 pan adapters - this is on a 6700.

    2. When you close SmartSDR thin client, it will remove all slices it has created.  When the last slice is removed, there is no more audio output.  So I think the answer to your question is "it depends" - if you want output to the radio to continue, create the slice(s) from your own application and then you get to decide what is the appropriate behavior.  

    3. No - status is across all connected clients and is identical for all.  The radio currently only recognizes one client and that is SmartSDR.  Sending anything other string in results in an error message from the radio.  If you identify as SmartSDR, the radio will only permit one client identifying with that name to connect at a time.

    Stu K6TU
  • IW7DMH, Enzo
    IW7DMH, Enzo Member ✭✭
    edited January 2017
    Very well dear Stu,

    I repeated three more times my tests and the behavior is exactly what you described on point 1)
    On the contrary, what I wrote is what it happens when my console starts and SSDR is already running.
    About point 2 and 3 now it is very clear what happens in the startup process.
    Today I setted a milestone on my kidding project and I like to share it with you (also to confirm that your patience and efforts were not wasted :)
    Thank you very much

    73' Enzo
    iw7dmh
    https://www.youtube.com/watch?v=O8qZl8YQhGM
  • Stu Phillips - K6TU
    Stu Phillips - K6TU Member ✭✭
    edited May 2020
    Awesome!
    Stu K6TU
  • Nigel
    Nigel Member ✭✭
    edited February 2016

    Great work Enzo.  I am trying to learn how to do control with an Arduino and am struggling.  Looks like you have cracked it.


    G0JKN - Nigel

  • IW7DMH, Enzo
    IW7DMH, Enzo Member ✭✭
    edited December 2016
    Oh thank you very much Nigel.
    It is still a work in progress and now it is mostly a matter of parsing strings along TCP/IP connection.
    I come from Java world (SJCP) and my C/C++ code is not still so good to share it. I am not very proud of it, even if it seems is working very well.
    For my project I had to use an Arduino Due as it has a very fast and powerful Arm processor. It has also 512 Mb of memory for your program and about 128 Mb memory of data space.
    Also, you need to use the "official" Ethernet shield. Clone shields have poor libraries and if you use them, probably you will lost your time as it happened to me. Official shield has a 100Mbs speed, not so bad for a microcontroller project.
    Look for my other posts in the community and you can find all informations that Stu gave me to take the full control over the Rig. Start from there.

    The to-do list I followed is here:
    1- getting ip address using dhcp;
    2- start searching for Flex rigs over the network (discovering protocol);
    3- connecting to the rig you discovered in step 2;
    4- getting the initial status of the rig (it could be already on) and start knowing all objects you can find; https://community.flexradio.com/flexradio/topics/smartsdr-tcp-ip-api-exaustive-command-list-request
    5- start changing the status of the rig (command protocol)
    6- .... more to came

    My original idea was a DIY, plug and play, console that could work away from any operating system. It seems against Flex philosophy but the TCP/IP API make it possible. I love the silent receiver of my 6300 and I like listening without "bell and whistle", just turn on and listen.

    73' Enzo
    iw7dmh
  • Ben Sinclair
    Ben Sinclair Member
    edited January 2017
    Great work! I'm interested in doing something similar. Where did you find that nice weighted knob?
  • Nigel
    Nigel Member ✭✭
    edited February 2016

    Well I am doing the same although im only using an Uno with a real Ethernet shield(as you suggested) I have got it to connect, display the version and handle on a character LCD and been able to send commands.

    But like you I need to be able to do that from a cold 6300 ie do the auto detect.

    anyone wanting the sketch is welcome to it... its actually quite easy to get it going!

    regards

    Nigel - G0JKN/W2

     

  • IW7DMH, Enzo
    IW7DMH, Enzo Member ✭✭
    edited December 2016
    Well Nigel, so you are already on step 3 and you are missing the step 2.
    Try to adapt the following code. It starts in the setup procedure and you have to simulate a main loop until you find a Flex rig.
    Before take a look at the UPD packet structure https://community.flexradio.com/flexradio/topics/wireshark-suggested-filters .
    Somewhere Stu said you can find two different length in Flex UDP packets, but I can't find that post. Anyway I choose to handle the one with 156 byte lenght.
    I hope this can help.

    73' Enzo
    iw7dmh

    ================================================================
    //******* SETUP *********
    void setup() {

        ....

        FlexRig.findAFlex();
       
        ....
    }


    //****** Static FindAflex Function **********

    #define UDP_DISCOVERING_PORT 4992
    #define UDP_TX_PACKET_MAX_SIZE 205


    FlexRig FlexRig::findAFlex() {

      EthernetUDP Udp;
      char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packets
      Udp.begin(UDP_DISCOVERING_PORT);
      FlexRig f=FlexRig();
      f.initBuffer(); 

      Serial.println("===Looking for Flex Rig (UDP)===");
     
      boolean found=false;
      while (!found) { 
         
          int packetSize = Udp.parsePacket();
         
          if(packetSize==156)
          {
            //Serial.print("Received packet - size ");
            //Serial.println(packetSize);
           
            // read the packet into packetBufffer
            Udp.read(packetBuffer,packetSize);
           
           
            //for (int i =0; i < 156; i++)
            //  Serial.print(packetBuffer[i]);
            //Serial.println(); 
             
            char model[36];
            for (int i =0; i < 36; i++)
              model[i]=packetBuffer[16+i];
           
            if (isAFlex(model)) {
                             
              Serial.println("===========Flex Rig=============");
          
              Serial.print("IP Address:");
              IPAddress remote = Udp.remoteIP();
              for (int i =0; i < 4; i++) {
                Serial.print(remote[i], DEC);
                f.ipAddress[i]=remote[i];       //Storing data into Flex Struct
                if (i < 3) Serial.print(".");  
              }
              Serial.println();
            
             
              Serial.print("Model Name:");
              for (int i=16; i < 52; i++) {
                f.modelName[i-16]=packetBuffer[i]; //Storing data into Flex Struct
                Serial.print(packetBuffer[i]);
              }
              Serial.println();
             
             
              Serial.print("Serial:"); 
              for (int i=52; i < 88; i++) {
                f.serial[i-52]=packetBuffer[i]; //Storing data into Flex Struct
                Serial.print(packetBuffer[i]);
              } 
              Serial.println(); 
             
              Serial.print("NickName:"); 
              for (int i=88; i < 124; i++) {
                f.nickName[i-88]=packetBuffer[i]; //Storing data into Flex Struct
                Serial.print(packetBuffer[i]);
              }
              Serial.println();
             
              Serial.print("Version:"); 
              for (int i=124; i < 156; i++) {
                f.softVersion[i-124]=packetBuffer[i]; //Storing data into Flex Struct
                Serial.print(packetBuffer[i]);
              }
             
              Serial.println();
             
              found=true;
            }
     
          }
        
          delay(100);
       
      } //main loop simulation - it is executed only once until a Flex rig is not found

       return f;   
    }


    //****** Dummy tester function *******
    boolean FlexRig::isAFlex(char* model) {
      boolean found=true;
      char pattern[10] = "FLEX-6300";
     
      for (int i=0;i<10;i++) {
        if (pattern[i]!=model[i]) {
          found=false;
          break; 
        }
      }

      return found;
    }
  • IW7DMH, Enzo
    IW7DMH, Enzo Member ✭✭
    edited December 2016
    It comes from the "audio" world: http://www.audioselection.it/product.php~idx~~~3008~~4421ALUB~.html
    Non a perfect grip but perfect wheight.
    The encoder comes from Ebay (search for "High resolution optical rotary encoder for DDS module VFO etc. 400 pulses/rev")
    It is perfect for vfo usage and it doesn't need to be debounced.

    73'
  • Nigel
    Nigel Member ✭✭
    edited February 2016

    Many thanks Enzo.  I took your code and ran with it! I Arduino Uno'ed it!! and I will post below.


    It uses an Arduino R3 with a "real" Ethernet shield and an Adafruit I2C LCD and buttons shield.  some output is on the LCD while debug info is in the serial port.

    I am going to move to the Mega and use a 7" 800x480 colour LCD with touch screen saves on buttons!!!.

    /* 

         Original code mainly from Enzo IW7DMH and modified(hacked) by Nigel G0JKN
                         other code from Nick Gammon
                please use this code but leave the names above  01/27/2015

    */


    #include <SPI.h>
    #include <Ethernet.h>
    #include <Wire.h>
    #include <Udp.h>
    #include <Adafruit_RGBLCDShield.h>
    #define RED 0x1
    #define YELLOW 0x3
    #define GREEN 0x2
    #define TEAL 0x6
    #define BLUE 0x4
    #define VIOLET 0x5
    #define WHITE 0x7
    #define UDP_DISCOVERING_PORT 4992
    #define UDP_TX_PACKET_MAX_SIZE 205

    Adafruit_MCP23017 mcp;
    Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
    // Enter a MAC address and IP address for your controller below.
    // The IP address will be dependent on your local network:
    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    IPAddress ip(169,254,86,57);
    IPAddress remote(0,0,0,0);
    String stringOne, stringTwo;
    int  ipAddress[4];
    char model[36];
    int modelName[12];
    int serial[36];
    int nickName[36];
    int softVersion[30];
    bool found = false;
    char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packets
    int packetSize = 0;

    // Enter the IP address of the server you're connecting to:
    byte server[4] = {0,0,0,0};
    EthernetClient client;

    unsigned int localPort = 4992;      // local port to listen on
    // An EthernetUDP instance to let us send and receive packets over UDP
    EthernetUDP Udp;

    boolean isitaFlex()
    {
     // boolean found=true;
      char pattern[10] = "FLEX-6300";
     
      for (int i=0;i<10;i++)
      {
        if (pattern[i]!=modelName[i])
        {
          Serial.print(pattern[i]);
          Serial.print("  ");
          Serial.println(modelName[i]);
          Serial.println("=========== Pattern match fail =============");
          return found = false;
          break; 
        }  
        return found = true;
      }
    }

    void processBuffer ()
    {
      isitaFlex();
      Serial.println("===== Pattern match passed =====");
      Serial.println("===========Flex Rig=============");
      Serial.print("IP Address:");
      IPAddress remote = Udp.remoteIP();
          for (int i =0; i < 4; i++)
          {
             Serial.print(remote[i], DEC);
             ipAddress[i]=remote[i];       //Storing data into Flex Struct
             //IPAddress server[i]=ipAddress[i];
             if (i < 3) Serial.print(".");  
           }
              Serial.println();
              Serial.print("Model Name:");
            for (int i=16; i < 52; i++)
            {
               modelName[i-16]=packetBuffer[i]; //Storing data into Flex Struct
               Serial.print(packetBuffer[i]);
             }
              Serial.println();
              Serial.print("Serial:"); 
              for (int i=52; i < 88; i++)
             {
               serial[i-52]=packetBuffer[i]; //Storing data into Flex Struct
               Serial.print(packetBuffer[i]);
             } 
              Serial.println();     
              Serial.print("NickName:"); 
              for (int i=88; i < 124; i++)
             {
               nickName[i-88]=packetBuffer[i]; //Storing data into Flex Struct
               Serial.print(packetBuffer[i]);
             }
              Serial.println();
              Serial.print("Version:"); 
              for (int i=124; i < 156; i++)
             {
               softVersion[i-124]=packetBuffer[i]; //Storing data into Flex Struct
               Serial.print(packetBuffer[i]);
             }
             
              Serial.println();
              delay (5000);
              connectFlex();
              found = true;  
    }

    void connectFlex()
    {
         lcd.clear();
         lcd.setCursor(0,0);
         lcd.print("connecting...");
         delay(1000);
        // Serial.print(remote[0..4]);
       // if you get a connection, report back via serial:
         if (client.connect((Udp.remoteIP()), 4992))
         {
         lcd.setCursor(0,1);
         lcd.print("connected");
         delay(2000);
          lcd.clear();
         }
    }
          


    void setup()
    {  // start the Ethernet and UDP:
     Ethernet.begin(mac,ip);
     Udp.begin(localPort);
     Serial.begin(115200);
     lcd.begin(16, 2);
     lcd.setBacklight(0x1);
     lcd.println("Looking for Flex");
     while (!found)
         { 
          int packetSize = Udp.parsePacket();    
          if(packetSize==156)
             {
               // read the packet into packetBufffer
               Udp.read(packetBuffer,packetSize);
               char model[36];
               for (int i =0; i < 36; i++)     
               model[i]=packetBuffer[16+i];
               processBuffer();   
              }     
          } //End of find a Flex !
    }


    void loop()
    {     
        
          
    }


    Regards


    Nigel Fenton - G0JKN/W2

  • IW7DMH, Enzo
    IW7DMH, Enzo Member ✭✭
    edited December 2016
    Very well Nigel!
    Consider you have to implement a very powerful text parser and you need a lot of cpu speed and a lot of memory.
    That is the reason I moved to a Due board. For the console you can see in my video, I choose these components http://www.sainsmart.com/sainsmart-due-5-lcd-touch-panel-sd-card-slot-tft-lcd-shield-kit-for-arduino.html and eight rotary encoder with embedded push-button.
    Using a Due I hope I can move (but don't know when) to a Udoo platform (http://www.udoo.org/ )

    73' Enzo
    iw7dmh
  • Nigel
    Nigel Member ✭✭
    edited February 2016
    Well Enzo, I looked ... liked and purchased an UDOO (quad) and WOW! both Android and Linux worked out of the box I've stuck to the linux as the Arduino IDE is easy on the linux version.  

    PS i was surprised at how fast the UDOO shipped.

    Nigel
  • IW7DMH, Enzo
    IW7DMH, Enzo Member ✭✭
    edited December 2016
    Well done Nigel, Udoo platform is really amazing.
    At the end of my Due tests I'll follow you

    73' Enzo
  • IW7DMH, Enzo
    IW7DMH, Enzo Member ✭✭
    edited January 2017
    Here are some improvements: now my Flex can be used without a personal computer.
    It would be nice having a feature for setting up fixed IP address so you don't need a router when the client is a very basic one like the Arduino boards.

    73'

    https://www.youtube.com/watch?v=HG1AUMpFoDw




  • James Whiteway
    edited March 2015
    Very nice work!!

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.