RadioHead
RH_TCP.h
1// RH_TCP.h
2// Author: Mike McCauley (mikem@aierspayce.com)
3// Copyright (C) 2014 Mike McCauley
4// $Id: RH_TCP.h,v 1.4 2015/08/13 02:45:47 mikem Exp $
5#ifndef RH_TCP_h
6#define RH_TCP_h
7
8#include <RHGenericDriver.h>
9#include <RHTcpProtocol.h>
10
11/////////////////////////////////////////////////////////////////////
12/// \class RH_TCP RH_TCP.h <RH_TCP.h>
13/// \brief Driver to send and receive unaddressed, unreliable datagrams via sockets on a Linux simulator
14///
15/// \par Overview
16///
17/// This class is intended to support the testing of RadioHead manager classes and simulated sketches
18/// on a Linux host.
19/// RH_TCP class sends messages to and from other simulator sketches via sockets to a 'Luminiferous Ether'
20/// simulator server (provided).
21/// Multiple instances of simulated clients and servers can run on a single Linux server,
22/// passing messages to each other via the etherSimulator.pl server.
23///
24/// Simple RadioHead sketches can be compiled and run on Linux using a build script and some support files.
25///
26/// \par Running simulated sketches
27///
28/// \code
29/// cd whatever/RadioHead
30/// # build the client for Linux:
31/// tools/simBuild examples/simulator/simulator_reliable_datagram_client/simulator_reliable_datagram_client.ino
32/// # build the server for Linux:
33/// tools/simBuild examples/simulator/simulator_reliable_datagram_server/simulator_reliable_datagram_server.ino
34/// # in one window, run the simulator server:
35/// tools/etherSimulator.pl
36/// # in another window, run the server
37/// ./simulator_reliable_datagram_server
38/// # in another window, run the client:
39/// ./simulator_reliable_datagram_client
40/// # see output:
41/// Sending to simulator_reliable_datagram_server
42/// got reply from : 0x02: And hello back to you
43/// Sending to simulator_reliable_datagram_server
44/// got reply from : 0x02: And hello back to you
45/// Sending to simulator_reliable_datagram_server
46/// got reply from : 0x02: And hello back to you
47/// ...
48/// \endcode
49///
50/// You can change the listen port and the simulated baud rate with
51/// command line arguments passed to etherSimulator.pl
52///
53/// \par Implementation
54///
55/// etherServer.pl is a conventional server written in Perl.
56/// listens on a TCP socket (defaults to port 4000) for connections from sketch simulators
57/// using RH_TCP as theur driver.
58/// The simulated sketches send messages out to the 'ether' over the TCP connection to the etherServer.
59/// etherServer manages the delivery of each message to any other RH_TCP sketches that are running.
60///
61/// \par Prerequisites
62///
63/// g++ compiler installed and in your $PATH
64/// Perl
65/// Perl POE library
66///
67class RH_TCP : public RHGenericDriver
68{
69public:
70 /// Constructor
71 /// \param[in] server Name and optionally the port number of the ether simulator server to contact.
72 /// Format is "name[:port]", where name can be any valid host name or address (IPV4 or IPV6).
73 /// The trailing :port is optional, and port can be any valid
74 /// port name or port number.
75 RH_TCP(const char* server = "localhost:4000");
76
77 /// Initialise the Driver transport hardware and software.
78 /// Make sure the Driver is properly configured before calling init().
79 /// \return true if initialisation succeeded.
80 virtual bool init();
81
82 /// Tests whether a new message is available
83 /// from the Driver.
84 /// On most drivers, this will also put the Driver into RHModeRx mode until
85 /// a message is actually received by the transport, when it will be returned to RHModeIdle.
86 /// This can be called multiple times in a timeout loop
87 /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv()
88 virtual bool available();
89
90 /// Wait until a new message is available from the driver.
91 /// Blocks until a complete message is received as reported by available()
92 /// \param[in] polldelay Time between polling available() in milliseconds. This can be useful
93 /// in multitaking environment like Linux to prevent waitAvailableTimeout
94 /// using all the CPU while polling for receiver activity
95 virtual void waitAvailable(uint16_t polldelay = 0);
96
97 /// Wait until a new message is available from the driver
98 /// or the timeout expires
99 /// Blocks until a complete message is received as reported by available()
100 /// \param[in] timeout The maximum time to wait in milliseconds
101 /// \param[in] polldelay Time between polling available() in milliseconds. This can be useful
102 /// in multitaking environment like Linux to prevent waitAvailableTimeout
103 /// using all the CPU while polling for receiver activity
104 /// \return true if a message is available as reported by available()
105 virtual bool waitAvailableTimeout(uint16_t timeout, uint16_t polldelay = 0);
106
107 /// Turns the receiver on if it not already on.
108 /// If there is a valid message available, copy it to buf and return true
109 /// else return false.
110 /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
111 /// You should be sure to call this function frequently enough to not miss any messages
112 /// It is recommended that you call it in your main loop.
113 /// \param[in] buf Location to copy the received message
114 /// \param[in,out] len Pointer to the number of octets available in buf. The number be reset to the actual number of octets copied.
115 /// \return true if a valid message was copied to buf
116 virtual bool recv(uint8_t* buf, uint8_t* len);
117
118 /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
119 /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
120 /// of 0 is NOT permitted. If the message is too long for the underlying radio technology, send() will
121 /// return false and will not send the message.
122 /// \param[in] data Array of data to be sent
123 /// \param[in] len Number of bytes of data to send (> 0)
124 /// \return true if the message length was valid and it was correctly queued for transmit
125 virtual bool send(const uint8_t* data, uint8_t len);
126
127 /// Returns the maximum message length
128 /// available in this Driver.
129 /// \return The maximum legal message length
130 virtual uint8_t maxMessageLength();
131
132 /// Sets the address of this node. Defaults to 0xFF. Subclasses or the user may want to change this.
133 /// This will be used to test the adddress in incoming messages. In non-promiscuous mode,
134 /// only messages with a TO header the same as thisAddress or the broadcast addess (0xFF) will be accepted.
135 /// In promiscuous mode, all messages will be accepted regardless of the TO header.
136 /// In a conventional multinode system, all nodes will have a unique address
137 /// (which you could store in EEPROM).
138 /// You would normally set the header FROM address to be the same as thisAddress (though you dont have to,
139 /// allowing the possibilty of address spoofing).
140 /// \param[in] address The address of this node.
141 void setThisAddress(uint8_t address);
142
143protected:
144
145private:
146 /// Connect to the address and port specified by the server constructor argument.
147 /// Prepares the socket for use.
148 bool connectToServer();
149
150 /// Check for new messages from the ether simulator server
151 /// \return true if no faults (not necessarily if there was an event)
152 bool checkForEvents();
153
154 /// Clear the receive buffer
155 void clearRxBuf();
156
157 /// Sends thisAddress to the ether simulator server
158 /// in a RHTcpThisAddress message.
159 /// \param[in] thisAddress The node address of this node
160 /// \return true if successful
161 bool sendThisAddress(uint8_t thisAddress);
162
163 /// Sends a message to the ether simulator server for delivery to
164 /// other nodes
165 /// \param[in] data Array of data to be sent
166 /// \param[in] len Number of bytes of data to send (> 0)
167 /// \return true if successful
168 bool sendPacket(const uint8_t* data, uint8_t len);
169
170 /// Address and port of the server to which messages are sent
171 /// and received using the protocol RHTcpPRotocol
172 const char* _server;
173
174 /// The TCP socket used to communicate with the message server
175 int _socket;
176
177 /// Buffer to receive RHTcpProtocol messages
178 uint8_t _rxBuf[RH_TCP_MAX_PAYLOAD_LEN + 5];
179 uint16_t _rxBufLen;
180 bool _rxBufValid;
181
182 /// Check whether the latest received message is complete and uncorrupted
183 void validateRxBuf();
184
185 // Used in the interrupt handlers
186 /// Buf is filled but not validated
187 volatile bool _rxBufFull;
188
189};
190
191/// @example simulator_reliable_datagram_client.ino
192/// @example simulator_reliable_datagram_server.ino
193
194#endif
Abstract base class for a RadioHead driver.
Definition: RHGenericDriver.h:42
Driver to send and receive unaddressed, unreliable datagrams via sockets on a Linux simulator.
Definition: RH_TCP.h:68
virtual bool waitAvailableTimeout(uint16_t timeout, uint16_t polldelay=0)
void setThisAddress(uint8_t address)
virtual bool init()
virtual uint8_t maxMessageLength()
RH_TCP(const char *server="localhost:4000")
virtual bool send(const uint8_t *data, uint8_t len)
virtual bool available()
virtual bool recv(uint8_t *buf, uint8_t *len)
virtual void waitAvailable(uint16_t polldelay=0)