This example use mbed-os default network interface through Cellular PDP context class . It use UDP or TCP socket with the given echo server and performs an echo transaction. This program can be used on the C027, C030-U201 and C030-R412M boards.

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 int main()
00239 {
00240     print_function("\n\nmbed-os-example-cellular\n");
00241     print_function("\n\nBuilt: %s, %s\n", __DATE__, __TIME__);
00242 #ifdef MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN
00243     print_function("\n\n[MAIN], plmn: %s\n", (MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN ? MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN : "NULL"));
00244 #endif
00245 
00246     print_function("Establishing connection\n");
00247 #if MBED_CONF_MBED_TRACE_ENABLE
00248     trace_open();
00249 #else
00250     dot_thread.start(dot_event);
00251 #endif // #if MBED_CONF_MBED_TRACE_ENABLE
00252 
00253 #if MBED_CONF_APP_SOCK_TYPE == NONIP
00254     iface = CellularContext::get_default_nonip_instance();
00255 #else
00256     iface = CellularContext::get_default_instance();
00257 #endif
00258 
00259     MBED_ASSERT(iface);
00260 
00261     // sim pin, apn, credentials and possible plmn are taken automatically from json when using NetworkInterface::set_default_parameters()
00262     iface->set_default_parameters();
00263 
00264     nsapi_error_t retcode = NSAPI_ERROR_NO_CONNECTION;
00265 
00266     /* Attempt to connect to a cellular network */
00267     if (do_connect() == NSAPI_ERROR_OK) {
00268         retcode = test_send_recv();
00269     }
00270 
00271     if (iface->disconnect() != NSAPI_ERROR_OK) {
00272         print_function("\n\n disconnect failed.\n\n");
00273     }
00274 
00275     if (retcode == NSAPI_ERROR_OK) {
00276         print_function("\n\nSuccess. Exiting \n\n");
00277     } else {
00278         print_function("\n\nFailure. Exiting \n\n");
00279     }
00280 
00281 #if MBED_CONF_MBED_TRACE_ENABLE
00282     trace_close();
00283 #else
00284     dot_thread.terminate();
00285 #endif // #if MBED_CONF_MBED_TRACE_ENABLE
00286 
00287     return 0;
00288 }
00289 // EOF