Version of easy-connect with the u-blox cellular platforms C027 and C030 added.

Dependents:   HelloMQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #ifndef MBED_EXTENDED_TESTS
00002     #error [NOT_SUPPORTED] Pressure tests are not supported by default
00003 #endif
00004 
00005 #include "mbed.h"
00006 #include "ESP8266Interface.h"
00007 #include "UDPSocket.h"
00008 #include "greentea-client/test_env.h"
00009 #include "unity/unity.h"
00010 #include "utest.h"
00011 
00012 using namespace utest::v1;
00013 
00014 
00015 #ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN
00016 #define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64
00017 #endif
00018 
00019 #ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX
00020 #define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000
00021 #endif
00022 
00023 #ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT
00024 #define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100
00025 #endif
00026 
00027 #ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED
00028 #define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564
00029 #endif
00030 
00031 #ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG
00032 #define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false
00033 #endif
00034 
00035 #ifndef MBED_CFG_ESP8266_TX
00036 #define MBED_CFG_ESP8266_TX D1
00037 #endif
00038 
00039 #ifndef MBED_CFG_ESP8266_RX
00040 #define MBED_CFG_ESP8266_RX D0
00041 #endif
00042 
00043 #ifndef MBED_CFG_ESP8266_DEBUG
00044 #define MBED_CFG_ESP8266_DEBUG false
00045 #endif
00046 
00047 #define STRINGIZE(x) STRINGIZE2(x)
00048 #define STRINGIZE2(x) #x
00049 
00050 
00051 // Simple xorshift pseudorandom number generator
00052 class RandSeq {
00053 private:
00054     uint32_t x;
00055     uint32_t y;
00056     static const int A = 15;
00057     static const int B = 18;
00058     static const int C = 11;
00059 
00060 public:
00061     RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED)
00062         : x(seed), y(seed) {}
00063 
00064     uint32_t next(void) {
00065         x ^= x << A;
00066         x ^= x >> B;
00067         x ^= y ^ (y >> C);
00068         return x + y;
00069     }
00070 
00071     void skip(size_t size) {
00072         for (size_t i = 0; i < size; i++) {
00073             next();
00074         }
00075     }
00076 
00077     void buffer(uint8_t *buffer, size_t size) {
00078         RandSeq lookahead = *this;
00079 
00080         for (size_t i = 0; i < size; i++) {
00081             buffer[i] = lookahead.next() & 0xff;
00082         }
00083     }
00084 
00085     int cmp(uint8_t *buffer, size_t size) {
00086         RandSeq lookahead = *this;
00087 
00088         for (size_t i = 0; i < size; i++) {
00089             int diff = buffer[i] - (lookahead.next() & 0xff);
00090             if (diff != 0) {
00091                 return diff;
00092             }
00093         }
00094         return 0;
00095     }
00096 };
00097 
00098 // Shared buffer for network transactions
00099 uint8_t *buffer;
00100 size_t buffer_size;
00101 
00102 // Tries to get the biggest buffer possible on the device. Exponentially
00103 // grows a buffer until heap runs out of space, and uses half to leave
00104 // space for the rest of the program
00105 void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) {
00106     size_t i = min;
00107     while (i < max) {
00108         void *b = malloc(i);
00109         if (!b) {
00110             i /= 4;
00111             if (i < min) {
00112                 i = min;
00113             }
00114             break;
00115         }
00116         free(b);
00117         i *= 2;
00118     }
00119 
00120     *buffer = (uint8_t *)malloc(i);
00121     *size = i;
00122     TEST_ASSERT(buffer);
00123 }
00124 
00125 void test_udp_packet_pressure() {
00126     generate_buffer(&buffer, &buffer_size,
00127         MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN,
00128         MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX);
00129     printf("MBED: Generated buffer %d\r\n", buffer_size);
00130 
00131     ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG);
00132     int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS));
00133     TEST_ASSERT_EQUAL(0, err);
00134 
00135     printf("MBED: UDPClient IP address is '%s'\n", net.get_ip_address());
00136     printf("MBED: UDPClient waiting for server IP and port...\n");
00137 
00138     greentea_send_kv("target_ip", net.get_ip_address());
00139 
00140     char recv_key[] = "host_port";
00141     char ipbuf[60] = {0};
00142     char portbuf[16] = {0};
00143     unsigned int port = 0;
00144 
00145     greentea_send_kv("host_ip", " ");
00146     greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
00147 
00148     greentea_send_kv("host_port", " ");
00149     greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
00150     sscanf(portbuf, "%u", &port);
00151 
00152     printf("MBED: Server IP address received: %s:%d \n", ipbuf, port);
00153 
00154     UDPSocket sock;
00155     SocketAddress udp_addr(ipbuf, port);
00156 
00157     Timer timer;
00158     timer.start();
00159 
00160     // Tests exponentially growing sequences
00161     for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN;
00162          size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX;
00163          size *= 2) {
00164         err = sock.open(&net);
00165         TEST_ASSERT_EQUAL(0, err);
00166         printf("UDP: %s:%d streaming %d bytes\r\n", ipbuf, port, size);
00167 
00168         sock.set_blocking(false);
00169 
00170         // Loop to send/recv all data
00171         RandSeq tx_seq;
00172         RandSeq rx_seq;
00173         size_t rx_count = 0;
00174         size_t tx_count = 0;
00175         int known_time = timer.read_ms();
00176         size_t window = buffer_size;
00177 
00178         while (tx_count < size || rx_count < size) {
00179             // Send out packets
00180             if (tx_count < size) {
00181                 size_t chunk_size = size - tx_count;
00182                 if (chunk_size > window) {
00183                     chunk_size = window;
00184                 }
00185 
00186                 tx_seq.buffer(buffer, chunk_size);
00187                 int td = sock.sendto(udp_addr, buffer, chunk_size);
00188 
00189                 if (td > 0) {
00190                     if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
00191                         printf("UDP: tx -> %d\r\n", td);
00192                     }
00193                     tx_seq.skip(td);
00194                     tx_count += td;
00195                 } else if (td != NSAPI_ERROR_WOULD_BLOCK) {
00196                     // We may fail to send because of buffering issues, revert to
00197                     // last good sequence and cut buffer in half
00198                     if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) {
00199                         window /= 2;
00200                     }
00201 
00202                     if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
00203                         printf("UDP: Not sent (%d), window = %d\r\n", td, window);
00204                     }
00205                 }
00206             }
00207 
00208             // Prioritize recieving over sending packets to avoid flooding
00209             // the network while handling erronous packets
00210             while (rx_count < size) {
00211                 int rd = sock.recvfrom(NULL, buffer, buffer_size);
00212                 TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK);
00213 
00214                 if (rd > 0) {
00215                     if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
00216                         printf("UDP: rx <- %d\r\n", rd);
00217                     }
00218 
00219                     if (rx_seq.cmp(buffer, rd) == 0) {
00220                         rx_seq.skip(rd);
00221                         rx_count += rd;
00222                         known_time = timer.read_ms();
00223                         if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) {
00224                             window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN;
00225                         }
00226                     }
00227                 } else if (timer.read_ms() - known_time >
00228                         MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) {
00229                     // Dropped packet or out of order, revert to last good sequence
00230                     // and cut buffer in half
00231                     tx_seq = rx_seq;
00232                     tx_count = rx_count;
00233                     known_time = timer.read_ms();
00234                     if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) {
00235                         window /= 2;
00236                     }
00237 
00238                     if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
00239                         printf("UDP: Dropped, window = %d\r\n", window);
00240                     }
00241                 } else if (rd == NSAPI_ERROR_WOULD_BLOCK) {
00242                     break;
00243                 }
00244             }
00245         }
00246 
00247         err = sock.close();
00248         TEST_ASSERT_EQUAL(0, err);
00249     }
00250 
00251     timer.stop();
00252     printf("MBED: Time taken: %fs\r\n", timer.read());
00253     printf("MBED: Speed: %.3fkb/s\r\n",
00254             8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - 
00255             MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read()));
00256 
00257     net.disconnect();
00258 }
00259 
00260 
00261 // Test setup
00262 utest::v1::status_t test_setup(const size_t number_of_cases) {
00263     GREENTEA_SETUP(120, "udp_echo");
00264     return verbose_test_setup_handler(number_of_cases);
00265 }
00266 
00267 Case cases[] = {
00268     Case("UDP packet pressure", test_udp_packet_pressure),
00269 };
00270 
00271 Specification specification(test_setup, cases);
00272 
00273 int main() {
00274     return !Harness::run(specification);
00275 }
00276