HRD 5.0 TCP/IP Protocol

The TCP/IP protocol used to communicate with HRD has changed in 5.0 to make the communications more robust.

The code is contained in the DLL HRDInterface001.dll which is shipped with HRD and is found in the same folder as the HRD executable. The source code is available and is downloadable on this page.

With HRD 4.0 a simple telnet-style approach was used, with HRD 5.0 a more professional TCP/IP protocol has been designed.


Source Code

The source code for the DLL is available here - it is a Visual Studio 6.0 C++ project. You should never need to compile the code, it is made available so that you can see what's going on.

It is possible that the code here will change from time to time, if you need the latest code for whatever reason just contact HB9DRV.

June 30th, 2009
Portals/1/SourceCode/HRDInterface001 2009-06-30.zip


Using The DLL

The DLL functions are contained in HRDInterfaceImports.h (see source code). Remember this is a UNICODE DLL, only wide (16-bits per character) strings are supported.

const BOOL HRDInterfaceConnect(LPCTSTR, const WORD);
void   HRDInterfaceDisconnect();
void   HRDInterfaceFreeString(LPTSTR);
DWORD   HRDInterfaceGetLastCode();
LPCTSTR   HRDInterfaceGetLastError();
const BOOL HRDInterfaceIsConnected();
void   HRDInterfaceLogfileMessage(CWnd* pWnd, UINT  nMsg);
LPTSTR   HRDInterfaceSendMessage(LPCTSTR, ...);
void   HRDInterfaceTracing(const BOOL);

Connecting To HRD

To connect call HRDInterfaceConnect(LPCTSTR lpszAddress, const WORD wPort) where:

lpszAddress is the address of the computer where HRD is running, for example:

wPort is the port number, typically 7809.

If HRD is not running on the same computer you must enable remote connections in HRD my selecting IP Server from the Tools menu and unchecking Same PC connections only. By default HRD only supports connections from the same PC.

 Disconnecting

Call HRDInterfaceDisconnect() to break the connection with HRD.


Sending A Message

Call HRDInterfaceSendMessage(LPCTSTR lpszFormat, ...) to send a message, the returned value is a string pointer, when you have finished with this string call HRDInterfaceFreeString(LPTSTR lpszString):

  • All requests and replies are terminated by hex 0x00.
  • Requests are case-insensitive.

Current Radio

Once you have connected using HRDInterfaceConnect() you must ask HRD about the current radio. HRD supports many simultaneous radio connections, for example HRD could be controlling a TS-480SAT and TS-2000 at the same time. The current radio is the the visible radio. 

Initialising

Send

Receive

Get Radio

Current radio, for example TS-2000. If not connected to a radio an empty string is returned.

Get Context

An internal context used by HRD to identify this radio connection, used in subsequent commands, this is always a numerical value.

Context

Note - context used from now on to ensure we address the correct radio in HRD as HRD can be connected to more than one radio at the same time. All requests start [c] where c is the context value returned from Get Context above.

Get

Note

Receive

[c] get Frequency

 

Returns frequency in Hz

[c] get dropdown-list XXX

XXX is a dropdown button, for example Mode

Comma-separated list of dropdown entries

[c] get slider-range RADIO XXX

RADIO is as returned above and XXX is title of slider, for example TS-2000 AF

Returns minpos,maxpos

[c] get user-active XXX

XXX is time in milliseconds

Returns 1 if the user has moved the mouse or pressed the keyboard in the last XXX milliseconds

[c] get button-select XXX

XXX is button title

Returns 1 if button is selected (highlighted), otherwise 0

[c] get dropdown-text XXX

XXX is the title of the dropdown button, for example Mode

Returns current selection (if any)

[c] get smeter-main

Returns main S-Meter, some radios have two S-Meters (for example TS-2000)

Returns max,raw,text where:

  • max = maximum numeric value,
  • raw = current numeric value,
  • text = current text value - e.g., S9

[c] get slider-pos RADIO XXX

RADIO is as returned above and XXX is title of slider

Returns current numeric position

 

Note: all get calls return a value, the returned string must be freed using HRDInterfaceFreeString(LPTSTR lpszString).

Example 1

In this C++ example a connection is made to HRD running on the same computer, the context and radio are read, then all buttons, dropdowns and sliders are returned.

BOOL bConnect = HRDInterfaceConnect(_T("localhost"), 7809);
if (bConnect)
{
LPTSTR  lpszContext = HRDInterfaceSendMessage(_T("Get Context"));
LPTSTR  lpszRadio   = HRDInterfaceSendMessage(_T("Get Radio"));
  LPTSTR lpszButtons   = HRDInterfaceSendMessage(_T("Get Buttons"));
  LPTSTR lpszDropdowns = HRDInterfaceSendMessage(_T("Get Dropdowns"));
  LPTSTR lpszSliders   = HRDInterfaceSendMessage(_T("Get Sliders"));
...
HRDInterfaceFreeString(lpszContext);
HRDInterfaceFreeString(lpszRadio);
HRDInterfaceFreeString(lpszButtons);
HRDInterfaceFreeString(lpszDropdowns);
HRDInterfaceFreeString(lpszSliders);
}

Set

Note

[c] set frequency-hz XXX

XXX is the frequency in Hertz

[c] set button-select XXX 0|1

XXX is button title, 0 (zero) to switch off, 1 (one) to switch on

[c] set dropdown XXX YYY IDX

XXX is a dropdown button title, YYY the dropdown button text entry, IDX the zero-based index in the dropdown list.

For example if the Mode dropdown contains AM,FM, USB,LSB,CW and you select USB then the command is

  • [c] set dropdown Mode USB 2

[c] set slider-pos RADIO XXX POS

RADIO is as returned above, XXX is title of slider and POS is the slider position, for example TS-2000 AF~Gain 55

 

Note: all set calls return the status, the returned string must be freed using HRDInterfaceFreeString(LPTSTR lpszString).

Note: Any spaces in the button titles and radio names must be replaced with ~, for example:

  • TF set is sent as TF~set,
  • RX Filter is sent as RX~Filter,
  • TS 480 is sent as TS~480.

Example 2

In the example a connection is made to HRD running on the same computer, the context (5) and radio (TS-2000) are read, then all buttons, dropdowns and sliders are returned. Changed are then made to the radio.

Radio Ctx Command Description
TS-2000   get radio Returns the radio model, a TS-2000
TS-2000 5 get context Returns the context (5), must be used in all Set commands
TS-2000 5 get buttons Retuns the buttons on the radio as a comma-separated list, for example: ATU,Ant 1,Ant 2, ...
TS-2000 5 get dropdowns Returns the dropdown buttons (such as mode) as a comma-separated list, for example Mode,RX Filter, Quick Mem,...
TS-2000 5 get sliders Returns all slider titles as a comma-separated list, for example AF Gain,RF Gain,RF Power,...
TS-2000 5 [5] set button-select ATU 0 Switch off the ATU
TS-2000 5 [5] set button-select Ant~1 1 Select antenna 1 spaces in the button title replaced with ~.
TS-2000 5 [5] set frequency-hz 14070000 Set the frequency to 14.070.000 (the PSK frequency on 20m)
TS-2000 5 [5] set dropdown mode fm 3 Selects FM, the 4th entry in the mode dropdown list (the index value is zero-based)
TS-2000 5 [5] set slider-pos TS-2000 AF~gain 100 Sets the audio level, spaces in the slider title replaced with ~.

 This C++ example implements the sequence of commands shown in the above table. The returned radio name must be checked to ensure it is not an empty string - if HRD is not displaying a radio window then an empty string is returned.

BOOL bConnect = HRDInterfaceConnect(_T("localhost"), 7809);
if (bConnect)
{
LPTSTR  lpszRadio   = HRDInterfaceSendMessage(_T("Get Radio"));
LPTSTR  lpszContext = HRDInterfaceSendMessage(_T("Get Context"));
  LPTSTR lpszButtons   = HRDInterfaceSendMessage(_T("Get Buttons"));
  LPTSTR lpszDropdowns = HRDInterfaceSendMessage(_T("Get Dropdowns"));
  LPTSTR lpszSliders   = HRDInterfaceSendMessage(_T("Get Sliders"));
LPTSTR lpszResult = NULL;
CString strContext;
CString strRadio = lpszRadio;

//
// Replace spaces with ~ in the radio name.
//
strRadio.Replace(_T(' '), _T('~'));

//
// Format context for all future Set calls.
//

strContext.Format(_T("[%s]"), lpszContext);

//
// Now the set commands, not that all button and slider names must have spaces replaced with ~.
//
lpszResult = HRDInterfaceSendMessage(_T("%s set button-select ATU 0"), strContext);
HRDInterfaceFreeString(lpszResult);
lpszResult = HRDInterfaceSendMessage(_T("%s set button-select Ant~1 1"), strContext);
HRDInterfaceFreeString(lpszResult);
lpszResult = HRDInterfaceSendMessage(_T("%s set frequency-hz 14070000"), strContext);
HRDInterfaceFreeString(lpszResult);
lpszResult = HRDInterfaceSendMessage(_T("%s set dropdown mode fm 3"), strContext);
HRDInterfaceFreeString(lpszResult);
lpszResult = HRDInterfaceSendMessage(_T("%s set slider-pos %s AF~gain 100"), strContext, strRadio);
HRDInterfaceFreeString(lpszResult);

//
// Free all strings.
//
HRDInterfaceFreeString(lpszContext);
HRDInterfaceFreeString(lpszRadio);
HRDInterfaceFreeString(lpszButtons);
HRDInterfaceFreeString(lpszDropdowns);
HRDInterfaceFreeString(lpszSliders);
}

TCP/IP Data Structure

Each message sent contains a header followed by the payload (the message sent / received).

Message Header

typedef struct
{
UINT  nSize;
 UINT  nSanity1;
 UINT  nSanity2;
 UINT  nChecksum;
 WCHAR szText[1];
} HRD_MSG_BLOCK;

nSize is the total size of the message in bytes including the trailing NULL at the end of szText.

nSanity1 is hex 1234ABCD

nSanity2 is hex ABCD1234

nChecksum is the checksum for the whole message, currently not used, must be zero.

szText is the test being sent as a UNICODE (wide) string. Although the array is defined with a size of 1 in practice it is allocated so that it is large enough to store the message being sent plus a trailing null. This is explained in the following C++ code snippet:

 //
 //  Allocate.
 //
 int     nMsgBytes  = sizeof(HRD_MSG_BLOCK) + sizeof(TCHAR) * (strMessage.GetLength() + 1);
 HRD_MSG_BLOCK* pMsgBlock  = (HRD_MSG_BLOCK*) new BYTE[nMsgBytes];
 BYTE*    pMsgBuffer = (BYTE*)pMsgBlock;
 ZeroMemory(pMsgBlock, nMsgBytes);
 
 pMsgBlock->nSize     = nMsgBytes;
 pMsgBlock->nSanity1  = 0x1234ABCD;
 pMsgBlock->nSanity2  = 0xABCD1234;
 pMsgBlock->nChecksum = 0;
 _tcscpy(pMsgBlock->szText, strMessage);

Copyright 2009 by Simon Brown, HB9DRV Terms Of Use Privacy Statement