This is an example based on mbed-os cellular APIs that demonstrates a TCP or UDP echo transaction with a public echo server.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * Copyright (c) 2017 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 #include "common_functions.h"
00019 #include "CellularNonIPSocket.h"
00020 #include "CellularDevice.h"
00021 #include "UDPSocket.h"
00022 #include "CellularLog.h"
00023 
00024 #define UDP 0
00025 #define TCP 1
00026 #define NONIP 2
00027 
00028 // Number of retries /
00029 #define RETRY_COUNT 3
00030 
00031 NetworkInterface *iface;
00032 
00033 // Echo server hostname
00034 const char *host_name = MBED_CONF_APP_ECHO_SERVER_HOSTNAME;
00035 
00036 // Echo server port (same for TCP and UDP)
00037 const int port = MBED_CONF_APP_ECHO_SERVER_PORT;
00038 
00039 static rtos::Mutex trace_mutex;
00040 
00041 #if MBED_CONF_MBED_TRACE_ENABLE
00042 static void trace_wait()
00043 {
00044     trace_mutex.lock();
00045 }
00046 
00047 static void trace_release()
00048 {
00049     trace_mutex.unlock();
00050 }
00051 
00052 static char time_st[50];
00053 
00054 static char* trace_time(size_t ss)
00055 {
00056     snprintf(time_st, 49, "[%08llums]", Kernel::get_ms_count());
00057     return time_st;
00058 }
00059 
00060 static void trace_open()
00061 {
00062     mbed_trace_init();
00063     mbed_trace_prefix_function_set( &trace_time );
00064 
00065     mbed_trace_mutex_wait_function_set(trace_wait);
00066     mbed_trace_mutex_release_function_set(trace_release);
00067 
00068     mbed_cellular_trace::mutex_wait_function_set(trace_wait);
00069     mbed_cellular_trace::mutex_release_function_set(trace_release);
00070 }
00071 
00072 static void trace_close()
00073 {
00074     mbed_cellular_trace::mutex_wait_function_set(NULL);
00075     mbed_cellular_trace::mutex_release_function_set(NULL);
00076 
00077     mbed_trace_free();
00078 }
00079 #endif // #if MBED_CONF_MBED_TRACE_ENABLE
00080 
00081 Thread dot_thread(osPriorityNormal, 512);
00082 
00083 void print_function(const char *format, ...)
00084 {
00085     trace_mutex.lock();
00086     va_list arglist;
00087     va_start( arglist, format );
00088     vprintf(format, arglist);
00089     va_end( arglist );
00090     trace_mutex.unlock();
00091 }
00092 
00093 void dot_event()
00094 {
00095     while (true) {
00096         ThisThread::sleep_for(4000);
00097         if (iface && iface->get_connection_status() == NSAPI_STATUS_GLOBAL_UP) {
00098             break;
00099         } else {
00100             trace_mutex.lock();
00101             printf(".");
00102             fflush(stdout);
00103             trace_mutex.unlock();
00104         }
00105     }
00106 }
00107 
00108 /**
00109  * Connects to the Cellular Network
00110  */
00111 nsapi_error_t do_connect()
00112 {
00113     nsapi_error_t retcode = NSAPI_ERROR_OK;
00114     uint8_t retry_counter = 0;
00115 
00116     while (iface->get_connection_status() != NSAPI_STATUS_GLOBAL_UP) {
00117         retcode = iface->connect();
00118         if (retcode == NSAPI_ERROR_AUTH_FAILURE) {
00119             print_function("\n\nAuthentication Failure. Exiting application\n");
00120         } else if (retcode == NSAPI_ERROR_OK) {
00121             print_function("\n\nConnection Established.\n");
00122         } else if (retry_counter > RETRY_COUNT) {
00123             print_function("\n\nFatal connection failure: %d\n", retcode);
00124         } else {
00125             print_function("\n\nCouldn't connect: %d, will retry\n", retcode);
00126             retry_counter++;
00127             continue;
00128         }
00129         break;
00130     }
00131     return retcode;
00132 }
00133 
00134 /**
00135  * Opens:
00136  * - UDP or TCP socket with the given echo server and performs an echo
00137  *   transaction retrieving current.
00138  * - Cellular Non-IP socket for which the data delivery path is decided
00139  *   by network's control plane CIoT optimisation setup, for the given APN.
00140  */
00141 nsapi_error_t test_send_recv()
00142 {
00143     nsapi_size_or_error_t retcode;
00144 #if MBED_CONF_APP_SOCK_TYPE == TCP
00145     TCPSocket sock;
00146 #elif MBED_CONF_APP_SOCK_TYPE == UDP
00147     UDPSocket sock;
00148 #elif MBED_CONF_APP_SOCK_TYPE == NONIP
00149     CellularNonIPSocket sock;
00150 #endif
00151 
00152 #if MBED_CONF_APP_SOCK_TYPE == NONIP
00153     retcode = sock.open((CellularContext*)iface);
00154 #else
00155     retcode = sock.open(iface);
00156 #endif
00157 
00158     if (retcode != NSAPI_ERROR_OK) {
00159 #if MBED_CONF_APP_SOCK_TYPE == TCP
00160         print_function("TCPSocket.open() fails, code: %d\n", retcode);
00161 #elif MBED_CONF_APP_SOCK_TYPE == UDP
00162         print_function("UDPSocket.open() fails, code: %d\n", retcode);
00163 #elif MBED_CONF_APP_SOCK_TYPE == NONIP
00164         print_function("CellularNonIPSocket.open() fails, code: %d\n", retcode);
00165 #endif
00166         return -1;
00167     }
00168 
00169     int n = 0;
00170     const char *echo_string = "TEST";
00171     char recv_buf[4];
00172 
00173     sock.set_timeout(15000);
00174 
00175 #if MBED_CONF_APP_SOCK_TYPE == NONIP
00176     retcode = sock.send((void*) echo_string, strlen(echo_string));
00177     if (retcode < 0) {
00178         print_function("CellularNonIPSocket.send() fails, code: %d\n", retcode);
00179         return -1;
00180     } else {
00181         print_function("CellularNonIPSocket: Sent %d Bytes\n", retcode);
00182     }
00183 
00184     n = sock.recv((void*) recv_buf, sizeof(recv_buf));
00185 
00186 #else
00187 
00188     SocketAddress sock_addr;
00189     retcode = iface->gethostbyname(host_name, &sock_addr);
00190     if (retcode != NSAPI_ERROR_OK) {
00191         print_function("Couldn't resolve remote host: %s, code: %d\n", host_name, retcode);
00192         return -1;
00193     }
00194 
00195     sock_addr.set_port(port);
00196 
00197 #if MBED_CONF_APP_SOCK_TYPE == TCP
00198     retcode = sock.connect(sock_addr);
00199     if (retcode < 0) {
00200         print_function("TCPSocket.connect() fails, code: %d\n", retcode);
00201         return -1;
00202     } else {
00203         print_function("TCP: connected with %s server\n", host_name);
00204     }
00205     retcode = sock.send((void*) echo_string, strlen(echo_string));
00206     if (retcode < 0) {
00207         print_function("TCPSocket.send() fails, code: %d\n", retcode);
00208         return -1;
00209     } else {
00210         print_function("TCP: Sent %d Bytes to %s\n", retcode, host_name);
00211     }
00212 
00213     n = sock.recv((void*) recv_buf, sizeof(recv_buf));
00214 #else
00215 
00216     retcode = sock.sendto(sock_addr, (void*) echo_string, strlen(echo_string));
00217     if (retcode < 0) {
00218         print_function("UDPSocket.sendto() fails, code: %d\n", retcode);
00219         return -1;
00220     } else {
00221         print_function("UDP: Sent %d Bytes to %s\n", retcode, host_name);
00222     }
00223 
00224     n = sock.recvfrom(&sock_addr, (void*) recv_buf, sizeof(recv_buf));
00225 #endif
00226 #endif
00227 
00228     sock.close();
00229 
00230     if (n > 0) {
00231         print_function("Received from echo server %d Bytes\n", n);
00232         return 0;
00233     }
00234 
00235     return -1;
00236 }
00237 
00238 void init_SkyWire4G()
00239 {
00240     DigitalOut myled(LED1);                             // Main LED
00241     DigitalOut skywire_en(D12);                        // Skywire Enable
00242     DigitalOut skywire_rts(D11);                       // Skywire Send
00243     DigitalOut green_LED(A1);                         // Green LED
00244     DigitalOut red_LED(A2);                           // Red LED
00245     DigitalOut blue_LED(A3);                          // Blue LED
00246 
00247     AnalogIn photo_trans(A0);                         // Photo Transistor
00248     AnalogIn pot(A5);                                 // Potentiometer
00249     DigitalIn button1(D3);                            // Button 1
00250     DigitalIn button2(A4);                            // Button 2
00251 #if 0
00252     I2C i2c(D14,D15);                                 // Setup I2C bus for sensors
00253 
00254     LPS331 pressure(i2c);                               // Pressure Sensor
00255     LM75B LM75_temp(D14,D15);                         // Temp Sensor
00256     // Accelerometer
00257     LIS3DH accel(i2c, LIS3DH_V_CHIP_ADDR, LIS3DH_DR_NR_LP_100HZ, LIS3DH_FS_2G);
00258     HTS221 humidity(D14, D15);                        // Humidity Sensor
00259 #endif
00260 
00261     // Turn on blue LED
00262     green_LED = 0;
00263     red_LED = 0;
00264     blue_LED = 1;
00265 
00266     skywire_rts=0;
00267     myled=0;
00268     printf("Starting Skywire board with LE910-EUG Demo...\n");
00269     printf("Waiting for Skywire to Boot...\n");
00270 
00271     //Enable Skywire
00272     skywire_en=0;
00273     ThisThread::sleep_for(2000);
00274     skywire_en=1;
00275     ThisThread::sleep_for(2000);
00276     skywire_en=0;
00277 
00278     myled=1;
00279         
00280     printf("Wait 15 seconds..\n");
00281     ThisThread::sleep_for(15000);
00282 }
00283 
00284 
00285 int main()
00286 {
00287     print_function("\n\nmbed-os-example-cellular\n");
00288     print_function("\n\nBuilt: %s, %s\n", __DATE__, __TIME__);
00289 #ifdef MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN
00290     print_function("\n\n[MAIN], plmn: %s\n", (MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN ? MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN : "NULL"));
00291 #endif
00292 
00293     init_SkyWire4G();
00294     print_function("Establishing connection\n");
00295 #if MBED_CONF_MBED_TRACE_ENABLE
00296     trace_open();
00297 #else
00298     dot_thread.start(dot_event);
00299 #endif // #if MBED_CONF_MBED_TRACE_ENABLE
00300 
00301 #if MBED_CONF_APP_SOCK_TYPE == NONIP
00302     iface = CellularContext::get_default_nonip_instance();
00303 #else
00304     iface = CellularContext::get_default_instance();
00305 #endif
00306 
00307     MBED_ASSERT(iface);
00308 
00309     // sim pin, apn, credentials and possible plmn are taken automatically from json when using NetworkInterface::set_default_parameters()
00310     iface->set_default_parameters();
00311 
00312     nsapi_error_t retcode = NSAPI_ERROR_NO_CONNECTION;
00313 
00314     /* Attempt to connect to a cellular network */
00315     if (do_connect() == NSAPI_ERROR_OK) {
00316         retcode = test_send_recv();
00317     }
00318 
00319     if (iface->disconnect() != NSAPI_ERROR_OK) {
00320         print_function("\n\n disconnect failed.\n\n");
00321     }
00322 
00323     if (retcode == NSAPI_ERROR_OK) {
00324         print_function("\n\nSuccess. Exiting \n\n");
00325     } else {
00326         print_function("\n\nFailure. Exiting \n\n");
00327     }
00328 
00329 #if MBED_CONF_MBED_TRACE_ENABLE
00330     trace_close();
00331 #else
00332     dot_thread.terminate();
00333 #endif // #if MBED_CONF_MBED_TRACE_ENABLE
00334 
00335     return 0;
00336 }
00337 // EOF