libcyberradio  22.01.24
RadioTransport.cpp
1 /***************************************************************************
2  * \file RadioTransport.cpp
3  * \brief Defines an interface for transporting data to and from a radio.
4  * \author DA
5  * \author NH
6  * \author MN
7  * \copyright (c) 2017 CyberRadio Solutions, Inc. All rights reserved.
8  *
9  * \note Requires C++11 compiler support.
10  *
11  ***************************************************************************/
12 
13 #include "LibCyberRadio/Driver/RadioTransport.h"
14 #include "LibCyberRadio/Common/Pythonesque.h"
15 #include "json/json.h"
16 #include <sstream>
17 #include <cstdio>
18 #include <sys/socket.h>
19 #include <arpa/inet.h>
20 #include <netdb.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <sys/select.h>
24 
25 
26 namespace LibCyberRadio
27 {
28 
29  namespace Driver
30  {
31 
33  bool json,
34  bool debug
35  ) :
36  Debuggable(debug, "RadioTransport"),
37  _isJson(json),
38  _tcpSocket(0),
39  _udpSocket(0),
40  _serial(NULL),
41  _httpsSession(NULL),
42  _httpsConnTestUrl(""),
43  _httpsApiCmdUrl(""),
44  _lastCmdErrInfo("")
45  {
46  this->debug("CONSTRUCTED\n");
47  }
48 
50  {
51  if ( isConnected() )
52  disconnect();
53  if (_httpsSession != NULL)
54  {
55  delete _httpsSession;
56  _httpsSession = NULL;
57  }
58  if (_serial != NULL)
59  {
60  delete _serial;
61  _serial = NULL;
62  }
63  this->debug("DESTROYED\n");
64  }
65 
67  Debuggable(other)
68  {
69  _isJson = other._isJson;
70  _tcpSocket = other._tcpSocket;
71  _udpSocket = other._udpSocket;
72  _serial = other._serial;
73  _httpsSession = other._httpsSession;
74  _httpsConnTestUrl = other._httpsConnTestUrl;
75  _httpsApiCmdUrl = other._httpsApiCmdUrl;
76  _lastCmdErrInfo = other._lastCmdErrInfo;
77  }
78 
80  {
81  Debuggable::operator=(other);
82  // Protect against self-assignment
83  if (this != &other)
84  {
85  _isJson = other._isJson;
86  _tcpSocket = other._tcpSocket;
87  _udpSocket = other._udpSocket;
88  _serial = other._serial;
89  _httpsSession = other._httpsSession;
90  _httpsConnTestUrl = other._httpsConnTestUrl;
91  _httpsApiCmdUrl = other._httpsApiCmdUrl;
92  _lastCmdErrInfo = other._lastCmdErrInfo;
93  }
94  return *this;
95  }
96 
97  void RadioTransport::setJson( bool json )
98  {
99  this->debug("[setJson] %s\n", json);
100  _isJson = json;
101  }
102 
103 
105  const std::string &mode,
106  const std::string &host_or_dev,
107  const int port_or_baudrate
108  )
109  {
110  this->debug("[connect] Called; mode=\"%s\", HorD=\"%s\", PorB=%d\n", mode.c_str(), host_or_dev.c_str(), port_or_baudrate);
111  bool ret = false;
112  if (mode == "https")
113  {
114  ret = connectHttps(host_or_dev, port_or_baudrate);
115  }
116  else if (mode == "udp")
117  {
118  ret = connectUdp(host_or_dev, port_or_baudrate);
119  }
120  else if (mode == "tcp")
121  {
122  ret = connectTcp(host_or_dev, port_or_baudrate);
123  }
124  else if (mode == "tty")
125  {
126  ret = connectTty(host_or_dev, port_or_baudrate);
127  }
128  this->debug("[connect] Returning %s\n", this->debugBool(ret));
129  return ret;
130  }
131 
133  {
134  this->debug("[disconnect] Called\n");
135  if (_httpsSession != NULL)
136  {
137  delete _httpsSession;
138  _httpsSession = NULL;
139  }
140  else if (_udpSocket > 0)
141  {
142  int ok = shutdown(_udpSocket, SHUT_RDWR);
143  if (ok != 0)
144  translateErrno();
145  }
146  else if (_tcpSocket > 0)
147  {
148  int ok = shutdown(_tcpSocket, SHUT_RDWR);
149  if (ok != 0)
150  translateErrno();
151  }
152  else if (_serial != NULL)
153  {
154  _serial->close();
155  delete _serial;
156  _serial = NULL;
157  }
158  this->debug("[disconnect] Returning\n");
159  }
160 
162  {
163  bool ret = (
164  (_httpsSession != NULL) ||
165  (_serial != NULL) ||
166  (_tcpSocket > 0) ||
167  (_udpSocket > 0)
168  );
169  return ret;
170  }
171 
173  const std::string &cmdString,
174  bool clearRx
175  )
176  {
177  this->debug("[sendCommand] Called; cmd=\"%s\"\n",
178  this->rawString(cmdString).c_str());
179  bool ret = false;
180  if (_httpsSession != NULL)
181  {
182  ret = sendCommandHttps(cmdString, clearRx);
183  }
184  else if (_serial != NULL)
185  {
186  ret = sendCommandTty(cmdString, clearRx);
187  }
188  else if (_udpSocket > 0)
189  {
190  ret = sendCommandUdp(cmdString, clearRx);
191  }
192  else if (_tcpSocket > 0)
193  {
194  ret = sendCommandTcp(cmdString, clearRx);
195  }
196  else
197  _lastCmdErrInfo = "Transport is not connected";
198  this->debug("[sendCommand] Returning %s\n", this->debugBool(ret));
199  return ret;
200  }
201 
203  double timeout
204  )
205  {
206  this->debug("[receive] Called\n");
207  BasicStringList ret;
208  if ( _isJson )
209  {
210  ret = receiveJson(timeout);
211  }
212  else
213  {
214  ret = receiveCli(timeout);
215  }
216  this->debug("[receive] Returning %u element%s\n", ret.size(),
217  ret.size() == 1 ? "" : "s");
218  return ret;
219  }
220 
222  {
223  return _lastCmdErrInfo;
224  }
225 
227  const std::string &host,
228  int port
229  )
230  {
231  this->debug("[connectTcp] Called; host=\"%s\", port=%d\n", host.c_str(), port);
232  _tcpSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
233  this->debug("[connectTcp] Socket created; FD=%d\n", _tcpSocket);
234  if (_tcpSocket > 0)
235  {
236  struct hostent *hent = gethostbyname(host.c_str());
237  char buf[128];
238  memset(buf, 0, sizeof(buf));
239  inet_ntop(AF_INET, hent->h_addr_list[0], buf, sizeof(buf));
240  this->debug("[connectTcp] Host IP address: %s\n", buf);
241  struct sockaddr_in addr;
242  memset(&addr, 0, sizeof(struct sockaddr_in));
243  addr.sin_family = AF_INET;
244  memcpy(&(addr.sin_addr.s_addr), hent->h_addr_list[0], hent->h_length);
245  addr.sin_port = htons(port);
246  this->debug("[connectTcp] Connecting\n");
247  int ok = ::connect(_tcpSocket, (const sockaddr*)&addr, sizeof(struct sockaddr_in));
248  this->debug("[connectTcp] -- ok = %d\n", ok);
249  if (ok != 0)
250  _tcpSocket = 0;
251  }
252  if (_tcpSocket <= 0)
253  {
254  _tcpSocket = 0;
255  translateErrno();
256  }
257  bool ret = (_tcpSocket > 0);
258  return ret;
259  }
260 
262  const std::string& host,
263  int port
264  )
265  {
266  this->debug("[connectUdp] Called; host=\"%s\", port=%d\n", host.c_str(), port);
267 
268  _udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
269  this->debug("[connectUdp] Socket created; FD=%d\n", _udpSocket);
270  if (_udpSocket > 0)
271  {
272  struct hostent *hent = gethostbyname(host.c_str());
273  char buf[128];
274  memset(buf, 0, sizeof(buf));
275  inet_ntop(AF_INET, hent->h_addr_list[0], buf, sizeof(buf));
276  this->debug("[connectUdp] Host IP address: %s\n", buf);
277  struct sockaddr_in addr;
278  memset(&addr, 0, sizeof(struct sockaddr_in));
279  addr.sin_family = AF_INET;
280  memcpy(&(addr.sin_addr.s_addr), hent->h_addr_list[0], hent->h_length);
281  addr.sin_port = htons(port);
282  this->debug("[connectUdp] Connecting\n");
283  int ok = ::connect(_udpSocket, (const sockaddr*)&addr, sizeof(struct sockaddr_in));
284  this->debug("[connectUdp] -- ok = %d\n", ok);
285  if (ok != 0)
286  _udpSocket = 0;
287  }
288  if (_udpSocket <= 0)
289  {
290  _udpSocket = 0;
291  translateErrno();
292  }
293  bool ret = (_udpSocket > 0);
294  return ret;
295  }
296 
298  const std::string &host,
299  int port
300  )
301  {
302  this->debug("[connectHttps] Called; host=\"%s\", port=%d\n", host.c_str(), port);
303  bool ret = false;
304  // Attempt to establish the HTTPS session
305  if ( _httpsSession == NULL )
306  _httpsSession = new HttpsSession( /*d_debug */ false);
307  if ( _httpsSession != NULL )
308  {
309  this->debug("[connectHttps] Session initialized\n");
310  // Form connection test and API command URLs
311  std::ostringstream oss;
312  oss << "https://" << host << ":" << port << "/";
313  _httpsConnTestUrl = oss.str();
314  oss << "api/command";
315  _httpsApiCmdUrl = oss.str();
316  // Test the connection
317  this->debug("[connectHttps] Testing connection; URL=%s\n",
318  _httpsConnTestUrl.c_str());
319  ret = _httpsSession->get(_httpsConnTestUrl, false);
320  // Destroy the session object if the connection test fails
321  if (!ret)
322  {
323  _lastCmdErrInfo = _httpsSession->getLastRequestErrorInfo();
324  delete _httpsSession;
325  _httpsSession = NULL;
326  }
327  }
328  else
329  _lastCmdErrInfo = "Failed to establish HTTPS session";
330  this->debug("[connectHttps] Returning %s\n", this->debugBool(ret));
331  return ret;
332  }
333 
335  const std::string& dev,
336  int baudrate
337  )
338  {
339  this->debug("[connectTty] Called; dev=\"%s\", baudrate=%d\n",
340  dev.c_str(), baudrate);
341  bool ret = false;
342  // Attempt to establish the TTY link
343  if ( _serial == NULL )
344  _serial = new ::LibCyberRadio::SerialPort(
345  dev, baudrate, 'N', 8, 1,
346  false, false, false
347  );
348  ret = _serial->open();
349  if ( ret )
350  {
351  this->debug("[connectTty] Serial link established\n");
352  // Test connection by sending an empty command
353  this->debug("[connectTty] Testing connection\n");
354  if ( sendCommand("\r\n") &&
355  (receive().size() > 0) )
356  {
357  }
358  else
359  {
360  std::ostringstream oss;
361  oss << "Connection test FAILED: ";
362  oss << _serial->getLastError();
363  _lastCmdErrInfo = oss.str();
364  ret = false;
365  }
366  }
367  else
368  {
369  std::ostringstream oss;
370  oss << "Serial link FAILED: ";
371  if ( _serial != NULL )
372  oss << _serial->getLastError();
373  else
374  oss << "Failed to establish serial link";
375  _lastCmdErrInfo = oss.str();
376  ret = false;
377  }
378  this->debug("[connectTty] Returning %s\n", this->debugBool(ret));
379  return ret;
380  }
381 
383  const std::string &cmdString,
384  bool clearRx
385  )
386  {
387  this->debug("[sendCommandTcp] Called; cmd=\"%s\"\n",
388  this->rawString(cmdString).c_str());
389  bool ret = false;
390  int bytes = send(_tcpSocket, cmdString.c_str(), cmdString.length(), 0);
391  this->debug("[sendCommandTcp] -- Bytes sent: %d\n", bytes);
392  if (bytes > 0)
393  {
394  ret = true;
395  }
396  else
397  {
398  translateErrno();
399  }
400  return ret;
401  }
402 
404  const std::string& cmdString,
405  bool clearRx
406  )
407  {
408  this->debug("[sendCommandUdp] Called; cmd=%s\n",
409  this->rawString(cmdString).c_str());
410  bool ret = false;
411  int bytes = send(_udpSocket, cmdString.c_str(), cmdString.length(), 0);
412  this->debug("[sendCommandUdp] -- Bytes sent: %d\n", bytes);
413  if (bytes > 0)
414  {
415  ret = true;
416  }
417  else
418  {
419  translateErrno();
420  }
421  return ret;
422  }
423 
425  const std::string &cmdString,
426  bool clearRx
427  )
428  {
429  this->debug("[sendCommandHttps] Called; cmd=\"%s\"\n",
430  this->rawString(cmdString).c_str());
431  bool ret = false;
432  if ( _httpsSession != NULL )
433  {
434  ret = _httpsSession->post(_httpsApiCmdUrl,
435  (void*)cmdString.c_str(),
436  cmdString.length(),
437  "application/json",
438  false);
439  this->debug("[sendCommandHttps] HTTPS response code = %d\n",
440  _httpsSession->getResponseCode());
441  // If the request failed, get the reason why.
442  if ( !ret )
443  {
444  // On a failed request, the radio may have returned a JSON
445  // response containing detailed response info. If this is
446  // the case, it's not a problem at the transport level, so
447  // we actually want to proceed as if the request succeeded.
448  // This allows extended error info to be passed up to the
449  // radio handler level.
450  Json::Reader reader;
451  Json::Value jsonResponse;
452  if ( reader.parse(_httpsSession->getResponseBody(),
453  jsonResponse, false) )
454  {
455  ret = true;
456  }
457  // If the radio did not return a JSON response, then
458  // indicate why the transport action failed.
459  else
460  {
461  _lastCmdErrInfo = _httpsSession->getLastRequestErrorInfo();
462  }
463  }
464  }
465  else
466  _lastCmdErrInfo = "Transport is not connected";
467  this->debug("[sendCommandHttps] Returning %s\n", this->debugBool(ret));
468  return ret;
469  }
470 
472  const std::string& cmdString,
473  bool clearRx
474  )
475  {
476  this->debug("[sendCommandTty] Called; cmd=\"%s\"\n",
477  this->rawString(cmdString).c_str());
478  bool ret = false;
479  if ( _serial->write(cmdString) )
480  {
481  this->debug("[sendCommandTty] -- Command sent\n");
482  ret = true;
483  }
484  else
485  {
486  _lastCmdErrInfo = _serial->getLastError();
487  }
488  return ret;
489  }
490 
492  double timeout
493  )
494  {
495  std::deque<std::string> ret;
496  if (_httpsSession != NULL) {
497  ret = receiveJsonHttps(timeout);
498  } else {
499  ret = receiveJsonUdp(timeout);
500  }
501  return ret;
502  }
503 
504  BasicStringList RadioTransport::receiveJsonUdp(
505  double timeout
506  )
507  {
508  this->debug("[receiveJsonUdp] Called; timeout=%0.1f\n", timeout);
509  BasicStringList ret;
510  std::ostringstream oss;
511  fd_set ins;
512  struct timeval tv;
513  tv.tv_sec = (long)timeout;
514  tv.tv_usec = (long)(1000000 * (timeout - (long)timeout));
515 
516  char buf[1024];
517  // data available
518  memset(buf, 0, sizeof(buf));
519  recv(_udpSocket, buf, sizeof(buf), 0);
520  this->debug("[receiveJsonUdp] Received chunk: \"%s\"\n", buf);
521  oss << buf;
522  this->debug("[receiveJsonUdp] Received: \"%s\"\n",
523  this->rawString(oss.str()).c_str());
524  Json::Reader reader;
525  Json::Value root;
526  std::string t = buf;
527  bool parsingSuccessful = reader.parse( t.c_str(), root ); //parse process
528  if ( !parsingSuccessful )
529  {
530  this->debug("[receiveJsonUdp] Parsing JSON Error\n");
531  }
532  Json::FastWriter fastWriter;
533  std::string output = fastWriter.write(root);
534  ret.push_back(output);
535  return ret;
536  }
537 
538 
540  double timeout
541  )
542  {
543  this->debug("[receiveJsonHttps] Called; timeout=%0.1f\n", timeout);
544  BasicStringList ret;
545  // When receiving JSON over HTTPS, the session object gets the
546  // HTTPS response body while servicing the request, so all we have
547  // to do is retrieve it.
548  if ( _httpsSession != NULL )
549  {
550  this->debug("[receiveJsonHttps] HTTPS response body = \"%s\"\n",
551  _httpsSession->getResponseBody().c_str());
552  ret = Pythonesque::Split(_httpsSession->getResponseBody(), "\n");
553  }
554  else
555  _lastCmdErrInfo = "Transport is not connected";
556  return ret;
557  }
558 
560  double timeout
561  )
562  {
563  std::deque<std::string> ret;
564  if (_udpSocket > 0)
565  ret = receiveCliUdp(timeout);
566  else if (_tcpSocket > 0)
567  ret = receiveCliTcp(timeout);
568  else if (_serial != NULL)
569  ret = receiveCliTty(timeout);
570  return ret;
571  }
572 
574  double timeout
575  )
576  {
577  this->debug("[receiveCliTcp] Called; timeout=%0.1f\n", timeout);
578  BasicStringList ret;
579  std::ostringstream oss;
580  fd_set ins;
581  struct timeval tv;
582  tv.tv_sec = (long)timeout;
583  tv.tv_usec = (long)(1000000 * (timeout - (long)timeout));
584  int nfds;
585  char buf[1024];
586  while (true)
587  {
588  FD_ZERO(&ins);
589  FD_SET(_tcpSocket, &ins);
590  this->debug("[receiveCliTcp] Selecting\n");
591  nfds = select(_tcpSocket + 1, &ins, NULL, NULL, timeout < 0 ? NULL : &tv);
592  this->debug("[receiveCliTcp] -- nfds = %d\n", nfds);
593  if (nfds > 0)
594  {
595  // data available
596  memset(buf, 0, sizeof(buf));
597  recv(_tcpSocket, buf, sizeof(buf), 0);
598  this->debug("[receiveCliTcp] Received chunk: \"%s\"\n", buf);
599  oss << buf;
600  // check for response terminator/prompt
601  if ( oss.str().rfind('>') != std::string::npos )
602  break;
603  }
604  else if (nfds == 0)
605  {
606  // timeout
607  this->debug("[receiveCliTcp] Timeout\n");
608  _lastCmdErrInfo = "Timeout";
609  break;
610  }
611  else
612  {
613  // Error in socket select
614  translateErrno();
615  this->debug("[receiveCliTcp] Socket select error: %s\n", _lastCmdErrInfo.c_str());
616  break;
617  }
618  }
619  this->debug("[receiveCliTcp] Received: \"%s\"\n",
620  this->rawString(oss.str()).c_str());
621  // Split the response into a list of non-empty strings
622  // -- Remove carriage returns and prompt character
623  std::string tmp = Pythonesque::Replace(Pythonesque::Replace(oss.str(), "\r", ""), ">", "");
624  // -- Split on newlines
625  BasicStringList tmpList = Pythonesque::Split(tmp, "\n");
626  // -- Compile the non-empty strings into a list
627  for (BasicStringList::iterator it = tmpList.begin(); it != tmpList.end(); it++)
628  {
629  tmp = Pythonesque::Rstrip(*it);
630  if ( !tmp.empty() )
631  ret.push_back(tmp);
632  }
633  this->debug("[receiveCliTcp] Returning %u elements\n", ret.size());
634  return ret;
635  }
636 
638  double timeout
639  )
640  {
641  BasicStringList ret;
642  return ret;
643  }
644 
646  double timeout
647  )
648  {
649  this->debug("[receiveCliTty] Called; timeout=%0.1f\n", timeout);
650  BasicStringList ret;
651  std::ostringstream oss;
652  std::string rsp = "X";
653  while ( rsp != "" )
654  {
655  rsp = _serial->read();
656  oss << rsp;
657  if ( Pythonesque::Endswith(oss.str(), ">") )
658  break;
659  }
660  this->debug("[receiveCliTty] Received: \"%s\"\n",
661  this->rawString(oss.str()).c_str());
662  // Split the response into a list of non-empty strings
663  // -- Remove carriage returns and prompt character
664  std::string tmp = Pythonesque::Replace(Pythonesque::Replace(oss.str(), "\r", ""), ">", "");
665  // -- Split on newlines
666  BasicStringList tmpList = Pythonesque::Split(tmp, "\n");
667  // -- Compile the non-empty strings into a list
668  for (BasicStringList::iterator it = tmpList.begin(); it != tmpList.end(); it++)
669  {
670  tmp = Pythonesque::Rstrip(*it);
671  if ( !tmp.empty() )
672  ret.push_back(tmp);
673  }
674  this->debug("[receiveCliTty] Returning %u elements\n", ret.size());
675  return ret;
676  }
677 
679  {
680  char buf[256];
681  memset(buf, 0, sizeof(buf));
682  this->debug(strerror_r(errno, buf, sizeof(buf)));
683  _lastCmdErrInfo = buf;
684  }
685 
686  } /* namespace Driver */
687 
688 } /* namespace LibCyberRadio */
static std::string Rstrip(const std::string &str, const std::string &chars=" \\\)
Strips trailing whitespace from the given string.
Definition: Pythonesque.cpp:41
virtual bool connect(const std::string &mode, const std::string &host_or_dev, const int port_or_baudrate)
Connects to the radio.
virtual BasicStringList receiveCliUdp(double timeout=-1)
Receives a client (AT-command-style) command response over UDP.
virtual std::string getLastCommandErrorInfo() const
Gets the error information for the last command.
virtual BasicStringList receiveCli(double timeout=-1)
Receives a client (AT-command-style) command response from the radio.
virtual long getResponseCode() const
Gets the HTTPS response code from the last request.
Debuggable & operator=(const Debuggable &other)
Assignment operator for Debuggable objects.
Definition: Debuggable.cpp:59
bool write(const std::string &data)
Writes data to the serial port.
Definition: SerialPort.cpp:271
virtual void disconnect()
Disconnects from the radio.
static std::string Replace(const std::string &str, const std::string &oldstr, const std::string &newstr, int count=INT_MAX)
Replaces occurrences of one substring with another within the given string.
Definition: Pythonesque.cpp:62
Class that supports debug output.
Definition: Debuggable.h:38
virtual BasicStringList receiveJson(double timeout=-1)
Receives a JSON-formatted command response from the radio.
bool open()
Open the serial port.
Definition: SerialPort.cpp:104
virtual ~RadioTransport()
Destroys a RadioTransport object.
virtual bool connectTty(const std::string &dev, int baudrate)
Connects to the radio using a serial link.
static BasicStringList Split(const std::string &str, const std::string &sep, int maxsplit=INT_MAX)
Splits the given string into a list of string tokens.
Definition: Pythonesque.cpp:77
std::string getLastError() const
Gets the last error message.
Definition: SerialPort.cpp:659
virtual bool connectUdp(const std::string &host, int port)
Connects to the radio using UDP.
virtual int debug(const char *format,...)
Outputs debug information.
Definition: Debuggable.cpp:95
BASIC_LIST_CONTAINER< std::string > BasicStringList
Type representing a list of strings.
Definition: BasicList.h:25
virtual std::string getResponseBody() const
Gets the HTTPS response body from the last request.
virtual bool connectHttps(const std::string &host, int port)
Connects to the radio using HTTPS.
static bool Endswith(const std::string &str, const std::string &suffix, int start=0, int end=INT_MAX)
Determines if the given string ends with the specified suffix.
virtual bool sendCommandTty(const std::string &cmdString, bool clearRx=true)
Sends a command to the radio over TTY.
Defines functionality for LibCyberRadio applications.
Definition: App.h:23
Generic radio transport class.
virtual bool get(const std::string &url, bool verify=true)
Gets data from a given URL over HTTPS.
virtual const char * debugBool(bool x)
Gets a debug output string for a Boolean value.
Definition: Debuggable.cpp:126
bool close()
Close the serial port.
Definition: SerialPort.cpp:212
virtual bool sendCommandHttps(const std::string &cmdString, bool clearRx=true)
Sends a command to the radio over HTTPS.
virtual std::string rawString(const std::string &data)
Gets a "raw" string representation of a given data string.
Definition: Debuggable.cpp:143
virtual bool post(const std::string &url, void *data, size_t length, const char *contentType="text/plain", bool verify=true)
Posts data to a given URL over HTTPS.
virtual void translateErrno()
Translates an errno value into an error message.
virtual BasicStringList receiveCliTty(double timeout=-1)
Receives a client (AT-command-style) command response over TTY.
Class that encapsulates an HTTPS session.
Definition: HttpsSession.h:29
virtual bool sendCommandTcp(const std::string &cmdString, bool clearRx=true)
Sends a command to the radio over TCP.
virtual BasicStringList receiveCliTcp(double timeout=-1)
Receives a client (AT-command-style) command response over TCP.
virtual bool sendCommand(const std::string &cmdString, bool clearRx=true)
Sends a command to the radio over the transport.
void setJson(bool json)
Allows user to set JSON.
virtual BasicStringList receive(double timeout=-1)
Receives a command response from the radio.
virtual bool isConnected() const
Gets whether the transport is connected.
virtual std::string getLastRequestErrorInfo() const
Gets the error information for the last request.
virtual BasicStringList receiveJsonHttps(double timeout=-1)
Receives a JSON-formatted command response from the radio using HTTPS.
RadioTransport & operator=(const RadioTransport &other)
Assignment operator for RadioTransport objects.
std::string read()
Reads data from the serial port.
Definition: SerialPort.cpp:231
RadioTransport(bool json=false, bool debug=false)
Constructs a RadioTransport object.
virtual bool sendCommandUdp(const std::string &cmdString, bool clearRx=true)
Sends a command to the radio over UDP.
virtual bool connectTcp(const std::string &host, int port)
Connects to the radio using TCP.