How do I use RTL-TCP?

Main forum to discuss RTL-SDR related topics.
Ben321
Posts: 33
Joined: Wed Feb 15, 2017 9:52 am

How do I use RTL-TCP?

Post by Ben321 » Sun Mar 05, 2017 9:29 pm

I'm running RTL-TCP.exe on my computer (which is a server program that allows other programs to get raw IQ data and send control commands, all via TCP), and am writing a TCP client program to communicate with it. It's MUCH easier to write a program that deals with networking (via MS Winsock in Windows in my case), than it is to write a program that deals with raw USB packets (as would be required if I wanted to directly communicate with my RTL-SDR).

However, there's a problem. There's ABSOLUTELY ZERO documentation on how to use RTL-TCP. I know there is a handshaking of some kind, because with SDR# it doens't just start processing any data sent to it (I tried that with a dummy server, which sent random data, and then tried connecting to it with SDR#, and it didn't accept the random data, which I had hoped it would see as a white noise radio signal). And I also know that once running, the connecting software can also send some commands to RTL-TCP.

Unfortunately, there is no documentation for the handshaking commands, and there's no documentation for the control commands. The entire RTL-TCP protocol has the feeling of being some kind of proprietary protocol that the company that made it is keeping as a trade secret. Yet I know it's not, as RTL-TCP.exe is an opensource program (as are all the other programs that came in the set). It's just that it completely lacks all documentation. It's like they expect you to throw random stuff at it, see what happens, write down your results, and end up compiling your own documentation from trial-and-error.

I just hope somebody here on these forums has a complete documentation of the RTL-TCP protocol, which they can post here, as a reply to this thread.

rtlsdrblog
Site Admin
Posts: 2563
Joined: Mon Nov 19, 2012 11:54 pm

Re: How do I use RTL-TCP?

Post by rtlsdrblog » Sun Mar 05, 2017 9:54 pm

I don't think there's any code documentation, you'd just have to delve into the open sourced code to understand it. You could try ask on the osmocom mailing list if any of the original devs could help you out.

Have a look at the old sdr# code rtl_tcp interface, it might help you out https://github.com/cgommel/sdrsharp/tree/master/RTLTCP.

hotpaw2
Posts: 127
Joined: Sat Jan 14, 2017 11:07 pm
Contact:

Re: How do I use RTL-TCP?

Post by hotpaw2 » Wed Mar 08, 2017 5:48 pm

Basic use of the rtl_tcp protocol is extremely simple.

Open a generic bidirectional TCP socket (default port 1234).

Uplink control is by sending 5 byte units, 1 byte command, 4 bytes of data (32 bit integer in little-endian format). You can get by with as few as 4 or 5 commands.

Here are a few of the command bytes:
// 0x01 set frequency in Hz
// 0x02 set sample rate in samples per second
// 0x03 set tuner gain mode : manual != 0, agc == 0
// 0x04 set tuner gain in 10th dB's
// 0x08 set RTL AGC (AGC_ON != 0)

There seem to be several forks of rtl_tcp on github, each with added custom commands (so there is unlikely to be any single "complete" doc).

The downlink data stream starts with 12 bytes of dongle ID (ignore if you only have one known dongle), then a continuous stream of bytes (pairs of interleaved IQ samples in uint8_t format), streaming at the selected sample rate until you close the socket. You might have to capture a 12 byte dongle ID (wireshark, et.al.) for use with other apps that need to know such.

So a simple rtl_tcp app can be written in maybe 100 lines of code (C, Swift, or even Basic). I wrote my first rtl_tcp streaming demodulator in Chipmunk Basic. A socket server app that pretended to be an online RTL-SDR was maybe a couple 100 lines of C to stream from rand().

The answer to documentation in the Open Source community is very often "please read the source code". So try that for more complete info.

remi
Posts: 4
Joined: Tue Apr 04, 2017 8:50 pm

Re: How do I use RTL-TCP?

Post by remi » Tue Apr 04, 2017 9:10 pm

hi,
One year ago , I was able to receive frame from rtl_tcp. I send few configuration commands.

If somebody do the same under linux, with gcc compilation options, i will be very interrested.
Next step for me : linux, and use data to a buffer for thread and use my filtering and demodulation code. Har for me
I'm an Rf Engenieer, not a software guy. Sorry for my very bad listing.
Remi

//#https://msdn.microsoft.com/en-us/librar ... s.85).aspx
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <stdint.h> // pour les int16 et int32
# include <cstdlib> // pour NOK calloc
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_PORT 1234
#define SERVTCP "192.168.0.9"

//int __cdecl main()
int main() {
// déclaration du bloc signal
struct signalCmplx SigIQbloc;
SigIQbloc.i = (int16_t*) calloc( NBLOC, sizeof(int) );
SigIQbloc.q = (int16_t*) calloc( NBLOC, sizeof(int) );
SigIQbloc.length = NBLOC;
// déclaration du bloc signal Out
struct signalCmplx SigIQout;
SigIQout.i = (int16_t*) calloc( NTABOUT, sizeof(int) );
SigIQout.q = (int16_t*) calloc( NTABOUT, sizeof(int) );
SigIQout.length = NTABOUT;

//----------------------
// Declare and initialize variables.
WSADATA wsaData;
int iResult;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
char *sendbuf = "this is a test ";
char recvbuf[DEFAULT_BUFLEN];
uint16_t recvbuflen = DEFAULT_BUFLEN;// qui remplace :int recvbuflen = DEFAULT_BUFLEN;
//----------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError() );
WSACleanup();
return 1;
}
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( SERVTCP );
clientService.sin_port = htons( DEFAULT_PORT );
//----------------------
// Connect to server.
iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
if ( iResult == SOCKET_ERROR) {
closesocket (ConnectSocket);
printf("Unable to connect to server: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}


/// envoi de commandes config RTLSDR
Sleep(5);
// sample rate
//char buffer[5]={0x02,0x00,0x03,0xD0,0x90}; // SR = 250 Khz
//char buffer[5]={0x02,0x00,0x0F,0xA0,0x00};// SR 1024 Mhz
char buffer[5]={0x02,0x00,0x24,0x9F,0x00};// SR 2.4Msps dwnl 38Mb/s
// Send an initial buffer
iResult = send( ConnectSocket, buffer, 5, 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent CMD: %ld\n", iResult);

Sleep(100);// FREQUENCE
//char buffer2[5]={0x01,0x06,0x12,0xDE,0xE0}; // frequence : 101.9Mhz 0x612DEE0
char buffer2[5]={0x01,0x05,0xDD,0x77,0x00}; // 98.4 musique boom boom
//char buffer2[5]={0x01,0x05,0xBE,0xF2,0x80}; //96.4 parole nonsaturee
//char buffer2[5]={0x01,0x05,0x4E,0x08,0x40}; // frequence : RFI 89 Mhz 0x 05 4E 08 40
iResult = send( ConnectSocket, buffer2, 5, 0 );
if (iResult == SOCKET_ERROR) { printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket); WSACleanup(); return 1; } printf("Bytes Sent CMD: %ld\n", iResult);
//rtlsdr_set_agc_mode (dev, 0, 0x19, on ? 0x03 : 0x05, 1);
Sleep(1); // AGC MODE
char buffer3[5]={0x08,0x00,0x00,0x00,0x00}; // 01 si auto
iResult = send( ConnectSocket, buffer3, 5, 0 );
if (iResult == SOCKET_ERROR) { printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket); WSACleanup(); return 1; } printf("Bytes Sent CMD: %ld\n", iResult);
// set gain mode
Sleep(1);// GAIN MODE
char buffer4[5]={0x03,0x00,0x00,0x00,0x01}; // 00 auto
iResult = send( ConnectSocket, buffer4, 5, 0 );
if (iResult == SOCKET_ERROR) { printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket); WSACleanup(); return 1; } printf("Bytes Sent CMD: %ld\n", iResult);
// tuner gain by index

Sleep(1);// AGC mode
char buffer5[5]={0x0D,0x00,0x00,0x00,0x00}; // 00
iResult = send( ConnectSocket, buffer5, 5, 0 );
if (iResult == SOCKET_ERROR) { printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket); WSACleanup(); return 1; } printf("Bytes Sent CMD: %ld\n", iResult);

Sleep(1);// TUNER GAIN 60d=0x3C
char buffer6[5]={0x04,0x00,0x00,0x00,0x3C}; // 00
iResult = send( ConnectSocket, buffer6, 5, 0 );
if (iResult == SOCKET_ERROR) { printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket); WSACleanup(); return 1; } printf("Bytes Sent CMD: %ld\n", iResult);

Sleep(100);// permet de voir un ll+ et un ll-
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1; }

/// reception PREMIERE TRAME : contient RTL0 : 10caract!
iResult = recv(ConnectSocket, recvbuf, 10, 0);
if ( iResult > 0 ) printf("\nN octets recu premiere=%d ", iResult);
else if ( iResult == 0 ) printf("Connection closed\n");
else printf("recv failed: %d\n", WSAGetLastError());


if (AFFICHAGE ==1) {printf(" data2:%s ",recvbuf);}// va de toute facon s'arrter au carac sero sur le print f

/// boucle acquisition vers fichier de sortie

remi
Posts: 4
Joined: Tue Apr 04, 2017 8:50 pm

Re: How do I use RTL-TCP?

Post by remi » Thu Apr 06, 2017 11:46 am

Hi,
I'm able to perform this transfert throught rtl tcp, under windows :-( with this kind of commands :

char buffer4[5]={0x03,0x00,0x00,0x00,0x01}; // 00 auto gain
iResult = send( ConnectSocket, buffer4, 5, 0 );
if (iResult == SOCKET_ERROR) { printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket); WSACleanup(); return 1; } printf("Bytes Sent CMD: %ld\n", iResult);

look at rtl_tcp for details commands. It works. Does sombody do the same with linux?
Thanks

Username
Posts: 568
Joined: Sun Oct 09, 2016 7:27 am

Re: How do I use RTL-TCP?

Post by Username » Mon Jun 05, 2017 8:56 am

hopefully here is someone who have more knowledge than me...

Its possible to run 2, 3, 4, 5, 6,... rtl-tcp at the same time? Its possible to use the use on the server side the serial number?
what is the maximal bandwith who are supported? there are a lot of wideband sdr on the market....

I hope gnu radio (sorry i never use it) can access to an rtl-tcp server?

rtlsdrblog
Site Admin
Posts: 2563
Joined: Mon Nov 19, 2012 11:54 pm

Re: How do I use RTL-TCP?

Post by rtlsdrblog » Tue Jun 06, 2017 11:46 am

You can use the -d flag to specify the dongle to be used. I suppose if you run each rtl_tcp connection on a different port number, then it should work.

Username
Posts: 568
Joined: Sun Oct 09, 2016 7:27 am

Re: How do I use RTL-TCP?

Post by Username » Tue Jun 06, 2017 11:52 am

like: .exe -d 12345 ???

Its possible to set an freq correction on the server so when i switch between the dongle i dont have to edit?
(like -ppm -40 ?!

rtlsdrblog
Site Admin
Posts: 2563
Joined: Mon Nov 19, 2012 11:54 pm

Re: How do I use RTL-TCP?

Post by rtlsdrblog » Tue Jun 06, 2017 12:43 pm

Yes, usually the first dongle plugged in will be -d 0, the second -d 1 etc.

I don't think there is any server-side PPM adjustment unfortunately. But SpyServer does have ability I think.

Username
Posts: 568
Joined: Sun Oct 09, 2016 7:27 am

Re: How do I use RTL-TCP?

Post by Username » Tue Jun 06, 2017 7:15 pm

Yes, usually the first dongle plugged in will be -d 0, the second -d 1 etc.
WTF?! :shock:
Now I have 4 Dongle in use with different Setups and Filter!!! Later I will use 30 - 40 !!!!

Post Reply