Mistake on this page?
Report an issue in GitHub or email us

Cellular API

CellularInterface class hierarchy

The CellularInterface class provides a C++ API for connecting to the internet over a Cellular device.

Getting started

  1. Choose an Mbed board that supports cellular, such as the UBLOX-C027 or MTS-DRAGONFLY.

  2. Clone mbed-os-example-cellular. Follow the instructions in the repository.

    1. Compile the code.
    2. Flash the board.

    You see output similar to the excerpt below:

mbed-os-example-cellular
Establishing connection ......

Connection Established.
TCP: connected with echo.mbedcloudtesting.com server
TCP: Sent 4 Bytes to echo.mbedcloudtesting.com
Received from echo server 4 Bytes


Success. Exiting

Basic working principles

You can use and extend a cellular interface in various different ways. For example,

  • Using AT commands to control sockets in an existing IP stack built into the cellular modem.

  • Using a PPP (Point-to-Point Protocol) pipe to pass IP packets between an Mbed OS supported IP stack and cellular modem device.

mbed-os-example-cellular uses PPP or AT mode depending on the modem. We can summarize this particular design as follows:

  • It uses an external IP stack, such as LWIP, or on-chip network stacks such as when the modem does not support PPP.
  • The easy cellular connection uses standard 3GPP AT 27.007 AT commands to set up the cellular modem and to register to the network.
  • After registration, the driver opens a PPP pipe using LWIP with the cellular modem and connects to the internet. If AT only mode is in use, then modem-specific AT commands are used for socket data control.

CellularInterface class reference

Public Types
typedef mbed::Callback< void(nsapi_error_t result, SocketAddress *address)> hostbyname_cb_t
 Hostname translation callback (for use with gethostbyname_async()). More...
Public Member Functions
virtual void set_credentials (const char *apn, const char *uname=0, const char *pwd=0)=0
 Set the cellular network credentials. More...
virtual void set_plmn (const char *plmn)=0
 Set the plmn. More...
virtual void set_sim_pin (const char *sim_pin)=0
 Set the PIN code for SIM card. More...
virtual nsapi_error_t connect (const char *sim_pin, const char *apn=0, const char *uname=0, const char *pwd=0)=0
 Attempt to connect to a cellular network with a PIN and credentials. More...
virtual nsapi_error_t connect ()=0
 Attempt to connect to a cellular network. More...
virtual nsapi_error_t disconnect ()=0
 Stop the interface. More...
virtual bool is_connected ()=0
 Check if the connection is currently established. More...
virtual const char * get_ip_address ()=0
 Get the local IP address. More...
virtual const char * get_netmask ()=0
 Get the local network mask. More...
virtual const char * get_gateway ()=0
 Get the local gateways. More...
virtual CellularInterfacecellularBase ()
 Return pointer to a CellularInterface. More...
virtual CellularInterfacecellularInterface ()
 Return pointer to a CellularInterface. More...
virtual void set_default_parameters ()
 defined(DOXYGEN_ONLY) More...
virtual void set_as_default ()
 Set network interface as default one. More...
virtual const char * get_mac_address ()
 Get the local MAC address. More...
virtual nsapi_error_t get_ipv6_link_local_address (SocketAddress *address)
 Get the IPv6 link local address. More...
virtual char * get_interface_name (char *interface_name)
 Get the network interface name. More...
virtual nsapi_error_t set_network (const char *ip_address, const char *netmask, const char *gateway)
 Configure this network interface to use a static IP address. More...
virtual nsapi_error_t set_dhcp (bool dhcp)
 Enable or disable DHCP on connecting the network. More...
virtual nsapi_error_t gethostbyname (const char *host, SocketAddress *address, nsapi_version_t version=NSAPI_UNSPEC, const char *interface_name=NULL)
 Translate a hostname to an IP address with specific version using network interface name. More...
virtual nsapi_value_or_error_t gethostbyname_async (const char *host, hostbyname_cb_t callback, nsapi_version_t version=NSAPI_UNSPEC, const char *interface_name=NULL)
 Translate a hostname to an IP address (asynchronous) using network interface name. More...
virtual nsapi_error_t gethostbyname_async_cancel (int id)
 Cancel asynchronous hostname translation. More...
virtual nsapi_error_t add_dns_server (const SocketAddress &address, const char *interface_name)
 Add a domain name server to list of servers to query. More...
virtual void attach (mbed::Callback< void(nsapi_event_t, intptr_t)> status_cb)
 Register callback for status reporting. More...
void add_event_listener (mbed::Callback< void(nsapi_event_t, intptr_t)> status_cb)
 Add event listener for interface. More...
void remove_event_listener (mbed::Callback< void(nsapi_event_t, intptr_t)> status_cb)
 Remove event listener from interface. More...
virtual nsapi_connection_status_t get_connection_status () const
 Get the connection status. More...
virtual nsapi_error_t set_blocking (bool blocking)
 Set asynchronous operation of connect() and disconnect() calls. More...
virtual EthInterfaceethInterface ()
 Return pointer to an EthInterface. More...
virtual WiFiInterfacewifiInterface ()
 Return pointer to a WiFiInterface. More...
virtual MeshInterfacemeshInterface ()
 Return pointer to a MeshInterface. More...
virtual EMACInterfaceemacInterface ()
 Return pointer to an EMACInterface. More...
Static Public Member Functions
static CellularInterfaceget_default_instance ()
 Get the default cellular interface. More...

Usage

To bring up the network interface:

  1. Instantiate an implementation of the CellularInterface class.
  2. Call the connect(pincode, apn) function with a PIN code for your SIM card and an APN for your network.
  3. Once connected, you can use Mbed OS network sockets as usual.

Cellular example: connection establishment

This example establishes connection with the cellular network using Mbed OS CellularInterface.

/*
 * Copyright (c) 2017 ARM Limited. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mbed.h"
#include "common_functions.h"
#include "CellularNonIPSocket.h"
#include "CellularDevice.h"
#include "UDPSocket.h"
#include "CellularLog.h"

#define UDP 0
#define TCP 1
#define NONIP 2

// Number of retries /
#define RETRY_COUNT 3

NetworkInterface *iface;

// Echo server hostname
const char *host_name = MBED_CONF_APP_ECHO_SERVER_HOSTNAME;

// Echo server port (same for TCP and UDP)
const int port = MBED_CONF_APP_ECHO_SERVER_PORT;

static rtos::Mutex trace_mutex;

#if MBED_CONF_MBED_TRACE_ENABLE
static void trace_wait()
{
    trace_mutex.lock();
}

static void trace_release()
{
    trace_mutex.unlock();
}

static char time_st[50];

static char* trace_time(size_t ss)
{
    snprintf(time_st, 49, "[%08llums]", Kernel::get_ms_count());
    return time_st;
}

static void trace_open()
{
    mbed_trace_init();
    mbed_trace_prefix_function_set( &trace_time );

    mbed_trace_mutex_wait_function_set(trace_wait);
    mbed_trace_mutex_release_function_set(trace_release);

    mbed_cellular_trace::mutex_wait_function_set(trace_wait);
    mbed_cellular_trace::mutex_release_function_set(trace_release);
}

static void trace_close()
{
    mbed_cellular_trace::mutex_wait_function_set(NULL);
    mbed_cellular_trace::mutex_release_function_set(NULL);

    mbed_trace_free();
}
#endif // #if MBED_CONF_MBED_TRACE_ENABLE

Thread dot_thread(osPriorityNormal, 512);

void print_function(const char *format, ...)
{
    trace_mutex.lock();
    va_list arglist;
    va_start( arglist, format );
    vprintf(format, arglist);
    va_end( arglist );
    trace_mutex.unlock();
}

void dot_event()
{
    while (true) {
        ThisThread::sleep_for(4000);
        if (iface && iface->get_connection_status() == NSAPI_STATUS_GLOBAL_UP) {
            break;
        } else {
            trace_mutex.lock();
            printf(".");
            fflush(stdout);
            trace_mutex.unlock();
        }
    }
}

/**
 * Connects to the Cellular Network
 */
nsapi_error_t do_connect()
{
    nsapi_error_t retcode = NSAPI_ERROR_OK;
    uint8_t retry_counter = 0;

    while (iface->get_connection_status() != NSAPI_STATUS_GLOBAL_UP) {
        retcode = iface->connect();
        if (retcode == NSAPI_ERROR_AUTH_FAILURE) {
            print_function("\n\nAuthentication Failure. Exiting application\n");
        } else if (retcode == NSAPI_ERROR_OK) {
            print_function("\n\nConnection Established.\n");
        } else if (retry_counter > RETRY_COUNT) {
            print_function("\n\nFatal connection failure: %d\n", retcode);
        } else {
            print_function("\n\nCouldn't connect: %d, will retry\n", retcode);
            retry_counter++;
            continue;
        }
        break;
    }
    return retcode;
}

/**
 * Opens:
 * - UDP or TCP socket with the given echo server and performs an echo
 *   transaction retrieving current.
 * - Cellular Non-IP socket for which the data delivery path is decided
 *   by network's control plane CIoT optimisation setup, for the given APN.
 */
nsapi_error_t test_send_recv()
{
    nsapi_size_or_error_t retcode;
#if MBED_CONF_APP_SOCK_TYPE == TCP
    TCPSocket sock;
#elif MBED_CONF_APP_SOCK_TYPE == UDP
    UDPSocket sock;
#elif MBED_CONF_APP_SOCK_TYPE == NONIP
    CellularNonIPSocket sock;
#endif

#if MBED_CONF_APP_SOCK_TYPE == NONIP
    retcode = sock.open((CellularContext*)iface);
#else
    retcode = sock.open(iface);
#endif

    if (retcode != NSAPI_ERROR_OK) {
#if MBED_CONF_APP_SOCK_TYPE == TCP
        print_function("TCPSocket.open() fails, code: %d\n", retcode);
#elif MBED_CONF_APP_SOCK_TYPE == UDP
        print_function("UDPSocket.open() fails, code: %d\n", retcode);
#elif MBED_CONF_APP_SOCK_TYPE == NONIP
        print_function("CellularNonIPSocket.open() fails, code: %d\n", retcode);
#endif
        return -1;
    }

    int n = 0;
    const char *echo_string = "TEST";
    char recv_buf[4];

    sock.set_timeout(15000);

#if MBED_CONF_APP_SOCK_TYPE == NONIP
    retcode = sock.send((void*) echo_string, strlen(echo_string));
    if (retcode < 0) {
        print_function("CellularNonIPSocket.send() fails, code: %d\n", retcode);
        return -1;
    } else {
        print_function("CellularNonIPSocket: Sent %d Bytes\n", retcode);
    }

    n = sock.recv((void*) recv_buf, sizeof(recv_buf));

#else

    SocketAddress sock_addr;
    retcode = iface->gethostbyname(host_name, &sock_addr);
    if (retcode != NSAPI_ERROR_OK) {
        print_function("Couldn't resolve remote host: %s, code: %d\n", host_name, retcode);
        return -1;
    }

    sock_addr.set_port(port);

#if MBED_CONF_APP_SOCK_TYPE == TCP
    retcode = sock.connect(sock_addr);
    if (retcode < 0) {
        print_function("TCPSocket.connect() fails, code: %d\n", retcode);
        return -1;
    } else {
        print_function("TCP: connected with %s server\n", host_name);
    }
    retcode = sock.send((void*) echo_string, strlen(echo_string));
    if (retcode < 0) {
        print_function("TCPSocket.send() fails, code: %d\n", retcode);
        return -1;
    } else {
        print_function("TCP: Sent %d Bytes to %s\n", retcode, host_name);
    }

    n = sock.recv((void*) recv_buf, sizeof(recv_buf));
#else

    retcode = sock.sendto(sock_addr, (void*) echo_string, strlen(echo_string));
    if (retcode < 0) {
        print_function("UDPSocket.sendto() fails, code: %d\n", retcode);
        return -1;
    } else {
        print_function("UDP: Sent %d Bytes to %s\n", retcode, host_name);
    }

    n = sock.recvfrom(&sock_addr, (void*) recv_buf, sizeof(recv_buf));
#endif
#endif

    sock.close();

    if (n > 0) {
        print_function("Received from echo server %d Bytes\n", n);
        return 0;
    }

    return -1;
}

int main()
{
    print_function("\n\nmbed-os-example-cellular\n");
    print_function("\n\nBuilt: %s, %s\n", __DATE__, __TIME__);
#ifdef MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN
    print_function("\n\n[MAIN], plmn: %s\n", (MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN ? MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN : "NULL"));
#endif

    print_function("Establishing connection\n");
#if MBED_CONF_MBED_TRACE_ENABLE
    trace_open();
#else
    dot_thread.start(dot_event);
#endif // #if MBED_CONF_MBED_TRACE_ENABLE

#if MBED_CONF_APP_SOCK_TYPE == NONIP
    iface = CellularContext::get_default_nonip_instance();
#else
    iface = CellularContext::get_default_instance();
#endif

    MBED_ASSERT(iface);

    // sim pin, apn, credentials and possible plmn are taken automatically from json when using NetworkInterface::set_default_parameters()
    iface->set_default_parameters();

    nsapi_error_t retcode = NSAPI_ERROR_NO_CONNECTION;

    /* Attempt to connect to a cellular network */
    if (do_connect() == NSAPI_ERROR_OK) {
        retcode = test_send_recv();
    }

    if (iface->disconnect() != NSAPI_ERROR_OK) {
        print_function("\n\n disconnect failed.\n\n");
    }

    if (retcode == NSAPI_ERROR_OK) {
        print_function("\n\nSuccess. Exiting \n\n");
    } else {
        print_function("\n\nFailure. Exiting \n\n");
    }

#if MBED_CONF_MBED_TRACE_ENABLE
    trace_close();
#else
    dot_thread.terminate();
#endif // #if MBED_CONF_MBED_TRACE_ENABLE

    return 0;
}
// EOF

Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.