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

  • 1
  • Question
  • Updated 3 years ago
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
Photo of IW7DMH, Enzo

IW7DMH, Enzo

  • 350 Posts
  • 83 Reply Likes

Posted 3 years ago

  • 1
Photo of Stu Phillips - K6TU

Stu Phillips - K6TU, Elmer

  • 642 Posts
  • 256 Reply Likes
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
Photo of IW7DMH, Enzo

IW7DMH, Enzo

  • 350 Posts
  • 83 Reply Likes
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
(Edited)
Photo of Stu Phillips - K6TU

Stu Phillips - K6TU, Elmer

  • 642 Posts
  • 256 Reply Likes
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
Photo of IW7DMH, Enzo

IW7DMH, Enzo

  • 350 Posts
  • 83 Reply Likes
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
(Edited)
Photo of IW7DMH, Enzo

IW7DMH, Enzo

  • 350 Posts
  • 83 Reply Likes
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;
}
(Edited)
Photo of Nigel - G0JKN/W2

Nigel - G0JKN/W2

  • 24 Posts
  • 0 Reply Likes

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

Photo of IW7DMH, Enzo

IW7DMH, Enzo

  • 350 Posts
  • 83 Reply Likes
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
(Edited)
Photo of Nigel - G0JKN/W2

Nigel - G0JKN/W2

  • 24 Posts
  • 0 Reply Likes
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
Photo of IW7DMH, Enzo

IW7DMH, Enzo

  • 350 Posts
  • 83 Reply Likes
Well done Nigel, Udoo platform is really amazing.
At the end of my Due tests I'll follow you

73' Enzo
Photo of Stu Phillips - K6TU

Stu Phillips - K6TU, Elmer

  • 642 Posts
  • 256 Reply Likes
Awesome!
Stu K6TU
Photo of Ben Sinclair

Ben Sinclair

  • 29 Posts
  • 0 Reply Likes
Great work! I'm interested in doing something similar. Where did you find that nice weighted knob?
Photo of IW7DMH, Enzo

IW7DMH, Enzo

  • 350 Posts
  • 83 Reply Likes
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'
(Edited)
Photo of IW7DMH, Enzo

IW7DMH, Enzo

  • 350 Posts
  • 83 Reply Likes
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'
Photo of James Whiteway

James Whiteway

  • 856 Posts
  • 186 Reply Likes
Very nice work!!