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