Connecting to a Telnet Server & Displaying the Contents

I'm having some telnet connection issues and need some help.

There are telnet servers that you can connect to that display ham radio stations that are on the amateur radio air waves. It sends a string (usually login:) and you type your call sign to login. It then spits out text like this with the spots when they appear. It's all automatic. No user intervention in the telnet session. The spots are filled out by others through a website entry and then are replicated through these telnet servers called "the DX cluster".

Here is an example of the output from one of these telnet sessions. New spots populate at the bottom.

DX de W6RK: 3556.5 K8ZZ Gallatin/Saline, IL CW 1901Z
DX de W6RK: 7056.5 K8ZZ Gallatin/Saline, IL CW 1906Z
DX de W6RK: 10124.5 K8ZZ Gallatin/Saline, IL CW 1907Z
DX de W6RK: 18091.5 K8ZZ Gallatin/Saline, IL CW 1912Z
DX de W6RK: 3556.5 K8ZZ Hamilton/White, IL CW 1947Z
DX de W6RK: 7056.5 K8ZZ Hamilton/White, IL CW 1950Z
DX de W6RK: 10124.5 K8ZZ Hamilton/White, IL CW 1952Z
DX de W6RK: 3556.5 K8ZZ Wabash, IL CW 2051Z
DX de W6RK: 7056.5 K8ZZ Wabash, IL CW 2056Z
DX de W6RK: 10124.5 K8ZZ Wabash, IL CW 2058Z
DX de W6RK: 18091.5 K8ZZ Wabash, IL CW 2103Z
DX de W6RK: 3556.5 K8ZZ Edwards, IL CW 2114Z
DX de W6RK: 7056.5 K8ZZ Edwards, IL CW 2117Z
DX de W6RK: 10124.5 K8ZZ Edwards, IL CW 2120Z
DX de W6RK: 24913.5 K8ZZ Edwards, IL CW 2128Z
DX de W6RK: 3556.5 K8ZZ Posey/Vanderburgh, IN CW 2211Z
DX de W6RK: 7056.5 K8ZZ Posey/Vanderburgh, IN CW 2217Z
DX de W6RK: 10124.5 K8ZZ Posey/Vanderburgh, IN CW 2220Z

I've loaded the telnet pallet, and have tried to connect, but I'm a little confused after the server sends me the "login:" I need to send it my call sign. Not even getting that far. Debug says "connection to the server timed out". I can telnet into it all day with no issues.

I'd like to read the above string into a JSON file so I can do some work, filter for specific states and modes and then spit it back out to a screen so we can view.

Thanks
Kyle

Hi. As telnet is just TCP, try putting a TCP request node set to port 22 & send your call sign (probably terminated with a cartridge return). See if it starts responding. Once you have it feeding back, we can split those strings into meaningful variables.

Got it working.

Used the TCP request node and first did a inject node to get through the telnet connect banner. Then used another inject node to send my call sign with a slight delay.

Only thing I could not figure out was when I set msg.payload to aa0z\r\n in the inject node (as a string), it would send that actual sequence including the \r\n at the end.

When I used a function node in line and set msg.payload = 'aa0z\r\n'; return msg; it worked fine and sent my call sign with a carriage return.

Good stuff.

Have you managed to convert you strings into meaningful objects and properties?

The inject node sends the characters you enter.

The junction node is pure JavaScript so \n is escaped as expected.

Thanks Steve. Makes sense. No coder here....so I'm slowing learning.

I haven't parsed the actual output yet, but I'm looking at the substr function as the length of the string is always 77 characters and the items I want to pull out are always at a fixed location.

I was heading down this path.

working with this string

DX de NX5M-#: 14030.0 FS5GL CW 20 dB 24 WPM CQ 1543Z

I was going to try --

let spot = msg.payload

let freq = spot.substr(18,7);
let call = spot.substr(27,6);
let comment = spot.substr(56,70);
let time = spot.substr(71,4);
return {payload:{freq:freq,call:call,comment:comment,time:time}};

Updated code...

Input

DX de NC7J-#: 14028.0 K4JJW 14 dB 20 WPM MOQP 1630Z

Function node :

let spot = msg.payload
let freq = spot.substr(17,7);
let call = spot.substr(26,6);
let comment = spot.substr(56,14);
let time = spot.substr(70,4);
return {payload:{freq:freq,call:call,comment:comment,time:time}};

Output ;

{"freq":"14028.0","call":"K4JJW ","comment":"MOQP ","time":"1630"}

On a roll here!!!

1 Like

Good stuff - just wanted to check you were on the right path.

1 Like

If you had a blank array and pushed that object into it (and then same for next etc) then you could feed straight into a ui_table node :wink:

( in fact if you used unshift rather than push it would add new ones to the top of the table instead of the bottom)

Thanks for the reply but totally over my head here with that comment.

I hit a snag on a variable length string that I need to format.....so I'm stuck on that at the moment.

Can you explain your first sentence again?

Will do when I get back to a decent keyboard. ( unless someone else jumps in first)

I suspect what Dave as alluding to is instead of writing the data to a file (as was your initial intension)...

... I believe Dave was suggesting you could just push the objects that you create (these objects >> {payload:{freq:freq,call:call,comment:comment,time:time}} <<) into an array & therefore no need to write to file. Then you could send that array to a UI_TABLE node (a dashboard node) for displaying a nicely formatted table of data

This is what ui_table looks like...

Ah, I see now.

Yes, I'd like to eventually see them in a table after comparing them to some other data, so this is good. I'll research how I can convert these objects into an array.

Thanks for the idea.

On my other issue, I have this data I'm getting out of my DX cluster. I'm reading data out of 4 telnet servers. 3 of them have the same format, so I can use the substr(x,y) function to format them into objects.

The 4th has a variable length with the county, 2 letter state, mode and the time.

DX de W6RK: 3556.5 K8ZZ Gallatin/Saline, IL CW 1901Z
DX de W6RK: 10124.5 K8ZZ Hamilton/White, IL CW 1952Z
DX de W6RK: 3556.5 K8ZZ Wabash, IL CW 2051Z

Everything before the colon is fixed (DX de W6RK). The frequency is at most 7 characters, could be less. The call (K8ZZ) can be anywhere between 4 to 8 characters. Then the county name. The "/" between two counties means that station is on a 2 county line. Then the 2 state code, mode (CW) This could be SSB, and then the time in Zulu.

My previous DX clusters all have fixed lengths for output, but I'm assuming if there is a trick to this last one, I could apply it to the previous outputs. Even if the objects have trailing blank spaces before or after the value, I'm assuming there is a way to trim those spaces before sticking them in a database.

Off the top of my head, you can do a conditional if () else (you will need to identify somehow which data you are working with. Perhaps the IP address?

if(deviceIP = "the_ip_of_the_odd_device") {
    //split the string like this
} else {
    //split the string like that instead
}
return msg;

search "mdn string trim"

example

You can even test it in the browser to see how it works.

1 Like

Picture is worth 1000 words here...thanks for taking the time to help me through this. Learning more and more as I go here.

Two flows.

For the top flow the output looks like this ;

DX de NX5M-#:    14030.0  FS5GL        CW 20 dB 24 WPM CQ             1543Z
DX de K3PA-#:     3553.5  WR5U         CW 8 dB 16 WPM CQ              1800Z
DX de K7VIC:     14076.0  OH8EZA                                      1800Z
DX de K0GU:      50313.0  XE2TT        DN70MQ<ES>DL44UC CQ            1801Z
DX de N5RZ-#:    10121.9  VE6JZN       CW 8 dB 14 WPM CQ              1852Z
DX de KO7SS-#:    7029.3  K9ZO         CW 18 dB 36 WPM CQ             1852Z

Everything is nice and even...and I can break it up with the substr call because the frequency and call are pretty much in the same place. I'm just grabbing the frequency, the call sign and time in zulu. If I get all the comment, great. It's not a priority. The substr call is in the function node and the object looks like the below. I've got some work to do to clean up the spaces, possibly with the trim command.

let spot = msg.payload
let freq = spot.substr(17,7);
let call = spot.substr(26,6);
let comment = spot.substr(54,15);
let time = spot.substr(70,4);
return {payload:{freq:freq,call:call,comment:comment,time:time}};

The formatted object looks like this ;

image

Now on to the bottom flow. Here is the output from that flow.

DX de W6RK: 3556.5 K8ZZ Hamilton/White, IL CW 1947Z
DX de W6RK: 7056.5 K8ZZ Hamilton/White, IL CW 1950Z
DX de W6RK: 10124.5 K8ZZ Hamilton/White, IL CW 1952Z
DX de W6RK: 3556.5 K8ZZ Wabash, IL CW 2051Z
DX de W6RK: 7056.5 K8ZZ Wabash, IL CW 2056Z
DX de W6RK: 3556.5 K8ZZ Posey/Vanderburgh, IN CW 2211Z
DX de W6RK: 7056.5 K8ZZ Posey/Vanderburgh, IN CW 2217Z
DX de W6RK: 10124.5 K8ZZ Posey/Vanderburgh, IN CW 2220Z

The first part is formatted nicely, but once you get into the frequency, all bets are off. The freq starts at position 13, but might be 7 characters, it might be 6 characters, a space then the call sign then a string with a state at the end, the mode then the time in zulu. For this flow, I need to capture the frequency and everything after into an object.

That is my roadblock at the moment.