David Rimer / RadioHead-148
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RH_TCP.h Source File

RH_TCP.h

00001 // RH_TCP.h
00002 // Author: Mike McCauley (mikem@aierspayce.com)
00003 // Copyright (C) 2014 Mike McCauley
00004 // $Id: RH_TCP.h,v 1.4 2015/08/13 02:45:47 mikem Exp $
00005 #ifndef RH_TCP_h
00006 #define RH_TCP_h
00007 
00008 #include <RHGenericDriver.h>
00009 #include <RHTcpProtocol.h>
00010 
00011 /////////////////////////////////////////////////////////////////////
00012 /// \class RH_TCP RH_TCP.h <RH_TCP.h>
00013 /// \brief Driver to send and receive unaddressed, unreliable datagrams via sockets on a Linux simulator
00014 ///
00015 /// \par Overview
00016 ///
00017 /// This class is intended to support the testing of RadioHead manager classes and simulated sketches 
00018 /// on a Linux host.
00019 /// RH_TCP class sends messages to and from other simulator sketches via sockets to a 'Luminiferous Ether' 
00020 /// simulator server (provided).
00021 /// Multiple instances of simulated clients and servers can run on a single Linux server,
00022 /// passing messages to each other via the etherSimulator.pl server.
00023 ///
00024 /// Simple RadioHead sketches can be compiled and run on Linux using a build script and some support files.
00025 ///
00026 /// \par Running simulated sketches
00027 ///
00028 /// \code
00029 /// cd whatever/RadioHead 
00030 /// # build the client for Linux:
00031 /// tools/simBuild examples/simulator/simulator_reliable_datagram_client/simulator_reliable_datagram_client.pde
00032 /// # build the server for Linux:
00033 /// tools/simBuild examples/simulator/simulator_reliable_datagram_server/simulator_reliable_datagram_server.pde
00034 /// # in one window, run the simulator server:
00035 /// tools/etherSimulator.pl
00036 /// # in another window, run the server
00037 /// ./simulator_reliable_datagram_server 
00038 /// # in another window, run the client:
00039 /// ./simulator_reliable_datagram_client
00040 /// # see output:
00041 /// Sending to simulator_reliable_datagram_server
00042 /// got reply from : 0x02: And hello back to you
00043 /// Sending to simulator_reliable_datagram_server
00044 /// got reply from : 0x02: And hello back to you
00045 /// Sending to simulator_reliable_datagram_server
00046 /// got reply from : 0x02: And hello back to you
00047 /// ...
00048 /// \endcode
00049 ///
00050 /// You can change the listen port and the simulated baud rate with 
00051 /// command line arguments passed to etherSimulator.pl
00052 ///
00053 /// \par Implementation
00054 ///
00055 /// etherServer.pl is a conventional server written in Perl.
00056 /// listens on a TCP socket (defaults to port 4000) for connections from sketch simulators
00057 /// using RH_TCP as theur driver.
00058 /// The simulated sketches send messages out to the 'ether' over the TCP connection to the etherServer.
00059 /// etherServer manages the delivery of each message to any other RH_TCP sketches that are running.
00060 ///
00061 /// \par Prerequisites
00062 ///
00063 /// g++ compiler installed and in your $PATH
00064 /// Perl
00065 /// Perl POE library
00066 ///
00067 class RH_TCP : public RHGenericDriver
00068 {
00069 public:
00070     /// Constructor
00071     /// \param[in] server Name and optionally the port number of the ether simulator server to contact.
00072     /// Format is "name[:port]", where name can be any valid host name or address (IPV4 or IPV6).
00073     /// The trailing :port is optional, and port can be any valid 
00074     /// port name or port number.
00075     RH_TCP(const char* server = "localhost:4000");
00076 
00077     /// Initialise the Driver transport hardware and software.
00078     /// Make sure the Driver is properly configured before calling init().
00079     /// \return true if initialisation succeeded.
00080     virtual bool init();
00081 
00082     /// Tests whether a new message is available
00083     /// from the Driver. 
00084     /// On most drivers, this will also put the Driver into RHModeRx mode until
00085     /// a message is actually received by the transport, when it will be returned to RHModeIdle.
00086     /// This can be called multiple times in a timeout loop
00087     /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv()
00088     virtual bool available();
00089 
00090     /// Wait until a new message is available from the driver.
00091     /// Blocks until a complete message is received as reported by available()
00092     virtual void waitAvailable();
00093 
00094     /// Wait until a new message is available from the driver
00095     /// or the timeout expires
00096     /// Blocks until a complete message is received as reported by available()
00097     /// \param[in] timeout The maximum time to wait in milliseconds
00098     /// \return true if a message is available as reported by available()
00099     virtual bool waitAvailableTimeout(uint16_t timeout);
00100 
00101     /// Turns the receiver on if it not already on.
00102     /// If there is a valid message available, copy it to buf and return true
00103     /// else return false.
00104     /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
00105     /// You should be sure to call this function frequently enough to not miss any messages
00106     /// It is recommended that you call it in your main loop.
00107     /// \param[in] buf Location to copy the received message
00108     /// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
00109     /// \return true if a valid message was copied to buf
00110     virtual bool recv(uint8_t* buf, uint8_t* len);
00111 
00112     /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
00113     /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
00114     /// of 0 is NOT permitted. If the message is too long for the underlying radio technology, send() will
00115     /// return false and will not send the message.
00116     /// \param[in] data Array of data to be sent
00117     /// \param[in] len Number of bytes of data to send (> 0)
00118     /// \return true if the message length was valid and it was correctly queued for transmit
00119     virtual bool send(const uint8_t* data, uint8_t len);
00120 
00121     /// Returns the maximum message length 
00122     /// available in this Driver.
00123     /// \return The maximum legal message length
00124     virtual uint8_t maxMessageLength();
00125 
00126     /// Sets the address of this node. Defaults to 0xFF. Subclasses or the user may want to change this.
00127     /// This will be used to test the adddress in incoming messages. In non-promiscuous mode,
00128     /// only messages with a TO header the same as thisAddress or the broadcast addess (0xFF) will be accepted.
00129     /// In promiscuous mode, all messages will be accepted regardless of the TO header.
00130     /// In a conventional multinode system, all nodes will have a unique address 
00131     /// (which you could store in EEPROM).
00132     /// You would normally set the header FROM address to be the same as thisAddress (though you dont have to, 
00133     /// allowing the possibilty of address spoofing).
00134     /// \param[in] address The address of this node.
00135     void setThisAddress(uint8_t address);
00136 
00137 protected:
00138 
00139 private:
00140     /// Connect to the address and port specified by the server constructor argument.
00141     /// Prepares the socket for use.
00142     bool connectToServer();
00143 
00144     /// Check for new messages from the ether simulator server
00145     void checkForEvents();
00146 
00147     /// Clear the receive buffer
00148     void clearRxBuf();
00149 
00150     /// Sends thisAddress to the ether simulator server
00151     /// in a RHTcpThisAddress message.
00152     /// \param[in] thisAddress The node address of this node
00153     /// \return true if successful
00154     bool sendThisAddress(uint8_t thisAddress);
00155 
00156     /// Sends a message to the ether simulator server for delivery to
00157     /// other nodes
00158     /// \param[in] data Array of data to be sent
00159     /// \param[in] len Number of bytes of data to send (> 0)
00160     /// \return true if successful
00161     bool sendPacket(const uint8_t* data, uint8_t len);
00162 
00163     /// Address and port of the server to which messages are sent
00164     /// and received using the protocol RHTcpPRotocol
00165     const char* _server;
00166 
00167     /// The TCP socket used to communicate with the message server
00168     int         _socket;
00169 
00170     /// Buffer to receive RHTcpProtocol messages
00171     uint8_t     _rxBuf[RH_TCP_MAX_PAYLOAD_LEN + 5];
00172     uint16_t    _rxBufLen;
00173     bool        _rxBufValid;
00174 
00175     /// Check whether the latest received message is complete and uncorrupted
00176     void            validateRxBuf();
00177 
00178     // Used in the interrupt handlers
00179     /// Buf is filled but not validated
00180     volatile bool   _rxBufFull;
00181 
00182 };
00183 
00184 /// @example simulator_reliable_datagram_client.pde
00185 /// @example simulator_reliable_datagram_server.pde
00186 
00187 #endif