Application description

The Serial LTE Modem (SLM) application demonstrates how to use the nRF9160 as a stand-alone LTE modem that can be controlled by proprietary AT commands.

Requirements

The application supports the following development kit:

Hardware platforms

PCA

Board name

Build target

nRF9160 DK

PCA10090

nrf9160dk_nrf9160

nrf9160dk_nrf9160

The sample is configured to compile and run as a non-secure application on nRF91’s Cortex-M33. Therefore, it automatically includes the Secure Partition Manager that prepares the required peripherals to be available for the application.

Overview

The nRF9160 SiP integrates both a full LTE modem and an application MCU, which enables you to run your LTE application directly on the nRF9160.

However, you might want to run your application on a different chip and use the nRF9160 only as a modem. For this use case, the serial LTE modem application provides an interface for controlling the LTE modem through AT commands.

The proprietary AT commands that are specific to the serial LTE modem application are described in the AT commands documentation. In addition to these proprietary AT commands, the application supports the nRF91 AT commands described in the AT Commands Reference Guide.

Communicating with the modem

The nRF9160 DK running the serial LTE modem application serves as the host. As a client, you can use either a PC or an external MCU.

Connecting with a PC

To connect to the nRF9160 DK with a PC, make sure that CONFIG_SLM_CONNECT_UART_0 is defined in the application. It is defined in the default configuration.

Use LTE Link Monitor to connect to the nRF9160 DK. See How to connect with LTE Link Monitor for instructions. You can then use this connection to send or receive AT commands over UART, and to see the log output of the nRF9160 DK.

Alternatively, you can use a terminal emulator like PuTTY to establish a terminal connection to the nRF9160 DK. See How to connect with PuTTY for instructions.

Note

The default AT command terminator is carriage return and line feed (\r\n). LTE Link Monitor supports this format. When connecting with another terminal emulator, make sure that the configured AT command terminator corresponds to the line terminator of your terminal. You can change the termination mode in the application configuration.

Connecting with an external MCU

If you run your user application on an external MCU (for example, an nRF52 Series DK), you can control the modem on the nRF9160 directly from the application. See the nRF52 client for serial LTE modem application repository for a sample implementation of such an application.

To connect with an external MCU, you must set the configuration options CONFIG_SLM_GPIO_WAKEUP and CONFIG_SLM_CONNECT_UART_2 in the serial LTE modem application configuration.

The following table shows how to connect an nRF52 Series DK to the nRF9160 DK to be able to communicate through UART:

nRF52 Series DK

nRF9160 DK

UART TX P0.6

UART RX P0.11

UART RX P0.8

UART TX P0.10

UART CTS P0.7

UART RTS P0.12

UART RTS P0.5

UART CTS P0.13

GPIO OUT P0.27

GPIO IN P0.31

UART instance in use:

  • nRF52840 or nRF52832 (UART0)

  • nRF9160 (UART2)

UART configuration:

  • Hardware flow control: enabled

  • Baud rate: 115200

  • Parity bit: no

  • Operation mode: IRQ

Note that the GPIO output level on nRF9160 side must be 3 V.

Configuration

See Configuring your application for information about how to permanently or temporarily change the configuration.

Configuration options

Check and configure the following configuration options for the sample:

CONFIG_SLM_CONNECT_UART_0 - UART 0

This option selects UART 0 for the UART connection. Select this option if you want to test the application with a PC.

CONFIG_SLM_CONNECT_UART_2 - UART 2

This option selects UART 2 for the UART connection. Select this option if you want to test the application with an external CPU.

CONFIG_SLM_GPIO_WAKEUP - Support of GPIO wakeup

This option enables using GPIO to wake up from sleep mode. Select this option if you want to test the application with an external CPU.

If this option is not selected, you must reset the kit to exit sleep mode.

CONFIG_SLM_INTERFACE_PIN - Interface GPIO to wake up or exit idle mode

This option specifies which interface GPIO to use for exiting sleep or idle mode. By default, P0.6 (Button 1 on the nRF9160 DK) is used when CONFIG_SLM_CONNECT_UART_0 is selected, and P0.31 is used when when CONFIG_SLM_CONNECT_UART_2 is selected.

Note that when CONFIG_SLM_CONNECT_UART_0 is selected, Button 1 can be used to exit idle mode, but not to wake up from sleep mode.

CONFIG_SLM_NULL_TERMINATION - NULL termination

This option configures the application to accept AT commands without a termination character.

CONFIG_SLM_CR_TERMINATION - CR termination

This option configures the application to accept AT commands ending with a carriage return.

CONFIG_SLM_LF_TERMINATION - LF termination

This option configures the application to accept AT commands ending with a line feed.

CONFIG_SLM_CR_LF_TERMINATION - CR+LF termination

This option configures the application to accept AT commands ending with carriage return and line feed.

CONFIG_SLM_SUPL_SERVER - SUPL server

This option specifies the SUPL server to use for retrieving SUPL A-GPS data.

CONFIG_SLM_SUPL_PORT - SUPL server port

This option specifies the port to use for the specified SUPL server.

CONFIG_SLM_FTP_SERVER_PORT - FTP service port on remote host

This option specifies the port to use when connecting to an FTP server.

CONFIG_SLM_FTP_USER_ANONYMOUS - FTP client anonymous login user

This option specifies the user name to use for anonymous login on an FTP server.

CONFIG_SLM_FTP_PASSWORD_ANONYMOUS - FTP client anonymous login password

This option specifies the password to use for anonymous login on an FTP server.

CONFIG_SLM_TCP_PROXY

This option enables additional AT commands for using a TCP proxy service.

CONFIG_SLM_UDP_PROXY

This option enables additional AT commands for using a UDP proxy service.

CONFIG_SLM_NATIVE_TLS

This option enables using Zephyr’s mbedTLS. It requires additional configuration. See Native TLS sockets for more information.

Additional configuration

Check and configure the following library options that are used by the sample:

To save power, console and logging output over UART_0 is disabled in this application. This information is logged to RTT instead. See Connecting via RTT for instructions on how to view this information.

To switch to UART output, change the following options in the prj.conf file:

# Segger RTT
CONFIG_USE_SEGGER_RTT=n
CONFIG_RTT_CONSOLE=n
CONFIG_UART_CONSOLE=y
CONFIG_LOG_BACKEND_RTT=n
CONFIG_LOG_BACKEND_UART=y

Configuration files

The sample provides predefined configuration files for both the parent image and the child image. You can find the configuration files in the applications/nrf9160/serial_lte_modem directory.

The following files are provided:

  • prj.conf - This configuration file contains the standard configuration for the serial LTE modem application.

  • overlay-native_tls.conf - This configuration file contains additional configuration options that are required to use Native TLS sockets. You can include it by adding -DOVERLAY_CONFIG=overlay-native_tls.conf to your build command. See Providing CMake options.

  • child_secure_partition_manager.conf - This configuration file contains the project-specific configuration for the Secure Partition Manager child image.

Native TLS sockets

By default, the secure socket (TLS/DTLS) is offloaded onto the modem. However, if you require customized TLS/DTLS features that are not supported by the modem firmware, you can use a native TLS socket instead. The serial LTE modem application will then handle all secure sockets used in TCP/IP, TCP/IP proxy, and MQTT.

If native TLS is enabled, the Credential storage management %CMNG command is overridden to map the security tag from the serial LTE modem application to the modem. You must use the overridden AT%CMNG command to provision credentials to the modem. Note that the serial LTE modem application supports security tags in the range of 0 - 214748364.

The configuration options that are required to enable the native TLS socket are defined in the overlay-native_tls.conf file.

Note

The following limitations exist for native TLS sockets:

  • PSK, PSK identity, and Public Key are currently not supported.

  • DTLS server is currently not supported.

  • AT%CMNG=1 is not supported.

  • FTP client and HTTP client do currently not support native TLS.

Building and running

This sample can be found under applications/nrf9160/serial_lte_modem in the nRF Connect SDK folder structure.

The sample is built as a non-secure firmware image for the nrf9160dk_nrf9160ns build target. Because of this, it automatically includes the Secure Partition Manager.

See Building and programming a sample application for information about how to build and program the application.

Testing

The testing instructions focus on testing the application with a PC client. If you have an nRF52 Series DK running a client application, you can also use this DK for testing the different scenarios.

After programming the sample to your development kit, test it by performing the following steps:

  1. Connect the kit to the computer using a USB cable. The kit is assigned a COM port (Windows) or ttyACM device (Linux), which is visible in the Device Manager.

  2. Connect to the kit with LTE Link Monitor. If you want to use a different terminal emulator, see Connecting with a PC.

  3. Reset the kit.

  4. Observe that the nRF9160 DK sends a Ready\r\n message on UART.

  5. Enter AT+CFUN=1 to turn on the modem and connect to the network.

  6. Enter AT+CFUN? and observe that the connection indicators in the LTE Link Monitor side panel turn green. This indicates that the modem is connected to the network.

  7. Send AT commands and observe the responses from the nRF9160 DK. See the following sections for typical test cases.

Testing generic AT commands

Complete the following steps to test the functionality provided by the Generic AT Commands:

  1. Retrieve the version of the serial LTE modem application.

    AT#XSLMVER
    #XSLMVER: 1.4
    OK
  2. Read the current baud rate.

    AT#XSLMUART?
    #SLMUART: 115200
    OK

    You can change the used baud rate with the corresponding set command, but note that LTE Link Monitor requires 115200 bps for communication.

  3. Retrieve a list of all supported proprietary AT commands.

    AT#XCLAC
    AT#XSLMVER
    AT#XSLEEP
    AT#XCLAC
    AT#XSOCKET
    AT#XSOCKETOPT
    AT#XBIND
    [...]
    OK
  4. Check the supported values for the sleep command, then put the board in sleep mode.

    AT#XSLEEP=?
    #XSLEEP: (0, 1)
    OK
    
    AT#XSLEEP=1

    Reset the board to exit sleep mode. If you are testing with an external MCU and CONFIG_SLM_GPIO_WAKEUP is enabled, you can wake up by GPIO as well.

Testing TCP/IP AT commands

The following sections show how to test the functionality provided by the TCP and UDP AT Commands.

TCP client
  1. Establish and test a TCP connection:

    1. Check the available values for the XSOCKET command.

      AT#XSOCKET=?
      #XSOCKET: (0, 1), (1, 2), (0, 1), <sec-tag>
      OK
    2. Open a TCP socket, read information (handle, protocol, and role) about the open socket, and set the receive time-out of the open socket to 30 seconds.

      AT#XSOCKET=1,1,0
      #XSOCKET: 1, 1, 0, 6
      OK
      
      AT#XSOCKET?
      #XSOCKET: 1, 6, 0
      OK
      
      AT#XSOCKETOPT=1,20,30
      OK
    3. Connect to a TCP server on a specified port. Replace example.com with the host name or IPv4 address of a TCP server and 1234 with the corresponding port. Then read the connection status. 1 indicates that the connection is established.

       AT#XCONNECT="example.com",1234
       #XCONNECT: 1
       OK
      
       AT#XCONNECT?
       #XCONNECT: 1
       OK
    4. Send plain text data to the TCP server and retrieve the returned data.

      AT#XSEND=1,"Test TCP"
      #XSEND: 8
      OK
      
      AT#XRECV
      PONG: b'Test TCP'
      #XRECV: 1, 17
      OK
    5. Send hexadecimal data to the TCP server and retrieve the returned data.

      AT#XSEND=0,"DEADBEEF"
      #XSEND: 4
      OK
      
      AT#XRECV
      PONG: b'\xde\xad\xbe\xef'
      #XRECV: 1, 25
      OK
    6. Close the socket and confirm its state.

      AT#XSOCKET=0
      #XSOCKET: 0, closed
      OK
      
      AT#XSOCKET?
      #XSOCKET: 0
      OK
  2. If you do not have a TCP server to test with, you can use TCP commands to request and receive a response from an HTTP server, for example, www.google.com:

    1. Open a TCP socket and connect to the HTTP server on port 80.

      AT#XSOCKET=1,1,0
      #XSOCKET: 1, 1, 0, 6
      OK
      
      AT#XCONNECT="google.com",80
      #XCONNECT: 1
      OK
    2. Send an HTTP request to the server.

      AT#XSEND=1,"HEAD / HTTP/1.1"
      #XSEND: 15
      OK
      
      AT#XSEND=0,"0D0A"
      #XSEND: 2
      OK
      
      AT#XSEND=1,"Host: www.google.com:443"
      #XSEND: 24
      OK
      
      AT#XSEND=0,"0D0A"
      #XSEND: 2
      OK
      
      AT#XSEND=1,"Connection: close"
      #XSEND: 17
      OK
      
      AT#XSEND=0,"0D0A0D0A"
      #XSEND: 4
      OK
    3. Receive the response from the server.

      AT#XRECV
      HTTP/1.1 200 OK
      Content-Type: text/html; charset=ISO-8859-1
      [...]
      #XRECV: 1, 576
      OK
      
      AT#XRECV
      [...]
      Connection: close
      #XRECV: 1, 147
      OK
    4. Close the socket.

      AT#XSOCKET=0
      #XSOCKET: 0, closed
      OK
  3. Test a TCP client with TCP proxy service (note that these commands are available only if CONFIG_SLM_TCP_PROXY is defined):

    1. Check the available values for the XTCPCLI command.

      AT#XTCPCLI=?
      #XTCPCLI: (0, 1, 2),<url>,<port>,<sec_tag>
      OK
    2. Create a TCP/TLS client and connect to a server. Replace example.com with the host name or IPv4 address of a TCP server and 1234 with the corresponding port. Then read information about the connection.

      AT#XTCPCLI=1,"example.com",1234
      #XTCPCLI: 2 connected
      OK
      
      AT#XTCPCLI?
      #XTCPCLI: 1, 0
      OK
    3. Send plain text data to the TCP server and retrieve ten bytes of the returned data.

      AT#XTCPSEND=1,"Test TCP"
      #XTCPSEND: 8
      OK
      
      AT#XTCPRECV=10
      PONG: b'Te
      #XTCPRECV: 10
      OK
    4. Send hexadecimal data to the TCP server and retrieve the returned data.

      AT#XTCPSEND=0,"DEADBEEF"
      #XTCPSEND: 4
      OK
      
      AT#XTCPRECV
      PONG: b'\xde\xad\xbe\xef'
      #XTCPRECV: 25
      OK
    5. Disconnect and confirm the status of the connection. -1 indicates that no connection is open.

      AT#XTCPCLI=0
      OK
      
      AT#XTCPCLI?
      #XTCPCLI: -1
      OK
  4. Test a TCP client with TCP proxy service in data mode (note that these commands are available only if CONFIG_SLM_TCP_PROXY is defined):

    1. Create a TCP/TLS client and connect to a server with data mode support. Replace example.com with the host name or IPv4 address of a TCP server and 1234 with the corresponding port. Then read information about the connection.

      AT#XTCPCLI=2,"example.com",1234
      #XTCPCLI: 1 connected
      OK
      
      AT#XTCPCLI?
      #XTCPCLI: 1, 1
      OK
    2. Send plain text data to the TCP server and retrieve the returned data.

      Test data mode
      PONG: b'Test data mode\r\n'
    3. Disconnect from the server.

      AT#XTCPCLI=0
      #XTCPCLI: disconnected
      OK
UDP client
  1. Test a UDP client with connectionless UDP:

    1. Open a UDP socket and read information (handle, protocol, and role) about the open socket.

      AT#XSOCKET=1,2,0
      #XSOCKET: 1, 2, 0, 17
      OK
      AT#XSOCKET?
      #XSOCKET: 1, 17, 0
      OK
    2. Send plain text data to a UDP server on a specified port. Replace example.com with the host name or IPv4 address of a UDP server and 1234 with the corresponding port. Then retrieve the returned data.

      AT#XSENDTO="example.com",1234,1,"Test UDP"
      #XSENDTO: 8
      OK
      AT#XRECVFROM
      PONG: Test UDP
      #XRECVFROM: 1, 14
      OK
    3. Send hexadecimal data to a UDP server on a specified port. Replace example.com with the host name or IPv4 address of a UDP server and 1234 with the corresponding port. Then retrieve the returned data.

      AT#XSENDTO="example.com",1234,0,"DEADBEEF"
      #XSENDTO: 4
      OK
      AT#XRECVFROM
      504F4E473A20DEADBEEF
      #XRECVFROM: 0, 20
      OK
    4. Close the socket.

      AT#XSOCKET=0
      #XSOCKET: 0, closed
      OK
  2. Test a UDP client with connection-based UDP:

    1. Open a UDP socket and connect to a UDP server on a specified port. Replace example.com with the host name or IPv4 address of a UDP server and 1234 with the corresponding port.

      AT#XSOCKET=1,2,0
      #XSOCKET: 1, 2, 0, 17
      OK
      
      AT#XCONNECT="example.com",1234
      #XCONNECT: 1
      OK
    2. Send plain text data to the UDP server and retrieve the returned data.

      AT#XSEND=1,"Test UDP"
      #XSEND: 8
      OK
      
      AT#XRECV
      PONG: Test UDP
      #XRECV: 1, 14
      OK
    3. Close the socket.

      AT#XSOCKET=0
      #XSOCKET: 0, closed
      OK
  3. Test a connection-based UDP client with UDP proxy service (note that these commands are available only if CONFIG_SLM_UDP_PROXY is defined):

    1. Check the available values for the XUDPCLI command.

      AT#XUDPCLI=?
      #XUDPCLI: (0, 1, 2),<url>,<port>,<sec_tag>
      OK
    2. Create a UDP client and connect to a server. Replace example.com with the host name or IPv4 address of a UDP server and 1234 with the corresponding port.

      AT#XUDPCLI=1,"example.com",1234
      #XUDPCLI: 2 connected
      OK
    3. Send plain text data to the UDP server and check the returned data.

      AT#XUDPSEND=1,"Test UDP"
      #XUDPSEND: 8
      OK
      #XUDPRECV: 1, 14
      PONG: Test UDP
    4. Send hexadecimal data to the UDP server and check the returned data.

      AT#XUDPSEND=0,"DEADBEEF"
      #XUDPSEND: 4
      OK
      #XUDPRECV: 0, 20
      504F4E473A20DEADBEEF
    5. Disconnect from the server.

      AT#XUDPCLI=0
      OK
  4. Test a connection-based UDP client with UDP proxy service in data mode (note that these commands are available only if CONFIG_SLM_UDP_PROXY is defined):

    1. Create a UDP client and connect to a server with data mode support. Replace example.com with the host name or IPv4 address of a UDP server and 1234 with the corresponding port. Then read information about the connection.

      AT#XUDPCLI=2,"example.com",1234
      #XUDPCLI: 1 connected
      OK
      
      AT#XUDPCLI?
      #XUDPCLI: 1, 1
      OK
    2. Send plain text data to the UDP server and retrieve the returned data.

      Test UDP by hostname
      PONG: Test UDP by hostname
    3. Disconnect from the server.

      AT#XUDPCLI=0
      #XUDPCLI: disconnected
      OK
TLS client

Before completing this test, you must update the CA certificate, the client certificate, and the private key to be used for the TLS connection in the modem. The credentials must use the security tag 16842755.

To store the credentials in the modem, use LTE Link Monitor. See Managing credentials in the LTE Link Monitor User Guide for instructions.

You must register the corresponding credentials on the server side.

  1. Establish and test a TLS connection:

    1. List the credentials that are stored in the modem with security tag 16842755.

      AT%CMNG=1,16842755
      %CMNG: 16842755,0,"0000000000000000000000000000000000000000000000000000000000000000"
      %CMNG: 16842755,1,"0101010101010101010101010101010101010101010101010101010101010101"
      %CMNG: 16842755,2,"0202020202020202020202020202020202020202020202020202020202020202"
      OK
    2. Open a TCP/TLS socket that uses the security tag 16842755 and connect to a TLS server on a specified port. Replace example.com with the host name or IPv4 address of a TLS server and 1234 with the corresponding port.

      AT#XSOCKET=1,1,0,16842755
      #XSOCKET: 1, 1, 0, 258
      OK
      
      AT#XCONNECT="example.com",1234
      #XCONNECT: 1
      OK
    3. Send plain text data to the TLS server and retrieve the returned data.

      AT#XSEND=1,"Test TLS client"
      #XSEND: 15
      OK
      
      AT#XRECV
      PONG: b'Test TLS client'
      #XRECV: 1, 24
      OK
    4. Close the socket.

      AT#XSOCKET=0
      #XSOCKET: 0, closed
      OK
  2. Test a TLS client with TCP proxy service (note that these commands are available only if CONFIG_SLM_TCP_PROXY is defined):

    1. Create a TCP/TLS client and connect to a server. Replace example.com with the host name or IPv4 address of a TLS server and 1234 with the corresponding port. Then read information about the connection.

      AT#XTCPCLI=1,"example.com",1234
      #XTCPCLI: 2 connected
      OK
      
      AT#XTCPCLI?
      #XTCPCLI: 1, 0
      OK
    2. Send plain text data to the TLS server and retrieve the returned data.

      AT#XTCPSEND=1,"Test TLS client"
      #XTCPSEND: 15
      OK
      #XTCPDATA: 1, 24
      
      AT#XTCPRECV
      PONG: b'Test TLS client'
      #XTCPRECV: 24
      OK
    3. Disconnect from the server.

      AT#XTCPCLI=0
      #XTCPCLI: disconnected
      OK
TCP server

To act as a TCP server, the nRF9160 DK must have a global private address. The radio network must be configured to route incoming IP packets to the nRF9160 DK.

To check if the setup is correct, use the AT+CGDCONT? command to check if the local IP address allocated by the network is a reserved private address of class A, B, or C (see Private addresses). If it is not, ping your nRF9160 DK from the destination server.

  1. Create a Python script client_tcp.py that acts a TCP client. See the following sample code (make sure to use the correct IP address and port):

    import socket
    import time
    
    host_addr = '000.000.000.00'
    host_port = 1234
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host_addr, host_port))
    time.sleep(1)
    print("Sending: 'Hello, TCP#1!")
    s.send(b"Hello, TCP#1!")
    time.sleep(1)
    print("Sending: 'Hello, TCP#2!")
    s.send(b"Hello, TCP#2!")
    data = s.recv(1024)
    print(data)
    
    time.sleep(1)
    print("Sending: 'Hello, TCP#3!")
    s.send(b"Hello, TCP#3!")
    time.sleep(1)
    print("Sending: 'Hello, TCP#4!")
    s.send(b"Hello, TCP#4!")
    time.sleep(1)
    print("Sending: 'Hello, TCP#5!")
    s.send(b"Hello, TCP#5!")
    time.sleep(1)
    data = s.recv(1024)
    print(data)
    
    print("Closing connection")
    s.close()
    
  2. Establish and test a TCP connection:

    1. Open a TCP socket, bind it to the TCP port that you want to use, and start listening. Replace 1234 with the correct port number.

      AT#XSOCKET=1,1,1
      #XSOCKET: 2, 1, 1, 6
      OK
      
      AT#XBIND=1234
      OK
      
      AT#XLISTEN
      OK
    2. Run the client_tcp.py script to start sending data to the server.

    3. Accept the connection from the client and start receiving and acknowledging the data.

      AT#XACCEPT
      #XACCEPT: connected with IP address
      #XACCEPT: 3
      OK
      
      AT#XRECV
      Hello, TCP#1!Hello, TCP#2!
      #XRECV: 1, 26
      OK
      
      AT#XSEND=1,"TCP1/2 received"
      #XSEND: 15
      OK
      
      AT#XRECV
      Hello, TCP#3!Hello, TCP#4!Hello, TCP#5!
      #XRECV: 1, 39
      OK
      
      AT#XSEND=1,"TCP3/4/5 received"
      #XSEND: 17
      OK
    4. Observe the output of the Python script:

      $ python client_tcp.py
      
      Sending: 'Hello, TCP#1!
      Sending: 'Hello, TCP#2!
      TCP1/2 received
      Sending: 'Hello, TCP#3!
      Sending: 'Hello, TCP#4!
      Sending: 'Hello, TCP#5!
      TCP3/4/5 received
      Closing connection
      
    5. Close the socket.

      AT#XSOCKET=0
      #XSOCKET: closed
      OK
  3. Test the TCP server with TCP proxy service (note that these commands are available only if CONFIG_SLM_TCP_PROXY is defined):

    1. Check the available values for the XTCPSVR command and read information about the current state.

      AT#XTCPSVR=?
      #XTCPSVR: (0, 1, 2),<port>,<sec_tag>
      OK
      
      AT#XTCPSVR?
      #XTCPSVR: -1, -1
      OK
    2. Create a TCP server and read information about the current state. Replace 1234 with the correct port number.

      AT#XTCPSVR=1,1234
      #XTCPSVR: 2 started
      OK
      
      AT#XTCPSVR?
      #XTCPSVR: 1, -1, 0
      OK
    3. Run the client_tcp.py script to start sending data to the server.

    4. Observe that the server accepts the connection from the client. Read information about the current state again.

      #XTCPSVR: IP address connected
      #XTCPDATA: 1, 13
      #XTCPDATA: 1, 13
      
      AT#XTCPSVR?
      #XTCPSVR: 1, 2, 0
      OK
    5. Start receiving and acknowledging the data.

      AT#XTCPRECV
      Hello, TCP#1!Hello, TCP#2!
      #XTCPRECV: 26
      OK
      
      AT#XTCPSEND=1,"TCP1/2 received"
      #XTCPSEND: 15
      OK
      #XTCPDATA: 1, 13
      #XTCPDATA: 1, 13
      #XTCPDATA: 1, 13
      
      AT#XTCPSVR?
      #XTCPSVR: 1, 2, 0
      OK
      
      AT#XTCPRECV
      Hello, TCP#3!Hello, TCP#4!Hello, TCP#5!
      #XTCPRECV: 39
      OK
      
      AT#XTCPSEND=1,"TCP3/4/5 received"
      #XTCPSEND: 17
      OK
    6. Observe the output of the Python script:

      $ python client_tcp.py
      
      Sending: 'Hello, TCP#1!
      Sending: 'Hello, TCP#2!
      TCP1/2 received
      Sending: 'Hello, TCP#3!
      Sending: 'Hello, TCP#4!
      Sending: 'Hello, TCP#5!
      TCP3/4/5 received
      Closing connection
      
    7. Read information about the current state and observe that the client disconnects.

      AT#XTCPSVR?
      #XTCPSVR: 1, 2, 0
      OK
      #XTCPSVR: timeout
      
      AT#XTCPSVR?
      #XTCPSVR: 1, -1, 0
      OK
    8. Stop the server.

      AT#XTCPSVR=0
      #XTCPSVR: stopped
      OK
      
      AT#XTCPSVR?
      #XTCPSVR: -1, -1
      OK
  4. Test the TCP server with TCP proxy service in data mode (note that these commands are available only if CONFIG_SLM_TCP_PROXY is defined):

    1. Create a TCP server and read information about the current state. Replace 1234 with the correct port number.

      AT#XTCPSVR=2,1234
      #XTCPSVR: 1 started
      OK
      
      AT#XTCPSVR?
      #XTCPSVR: 1, -1, 1
      OK
    2. Run the client_tcp.py script to start sending data to the server.

    3. Observe that the server accepts the connection from the client and starts receiving data. Acknowledge the received data.

      #XTCPSVR: IP address connected
      Hello, TCP#1!Hello, TCP#2!TCP1/2 received
      Hello, TCP#3!Hello, TCP#4!Hello, TCP#5!TCP3/4/5 received
    4. Observe the output of the Python script:

      $ python client_tcp.py
      
      Sending: 'Hello, TCP#1!
      Sending: 'Hello, TCP#2!
      TCP1/2 received
      Sending: 'Hello, TCP#3!
      Sending: 'Hello, TCP#4!
      Sending: 'Hello, TCP#5!
      TCP3/4/5 received
      Closing connection
      
    5. Stop the server.

      AT#XTCPSVR=0
      #XTCPSVR: stopped
      OK
UDP server

To act as a UDP server, the nRF9160 DK must have a global private address. The radio network must be configured to route incoming IP packets to the nRF9160 DK.

To check if the setup is correct, use the AT+CGDCONT? command to check if the local IP address allocated by the network is a reserved private address of class A, B, or C (see Private addresses). If it is not, ping your nRF9160 DK from the destination server.

  1. Create a Python script client_udp.py that acts a UDP client. See the following sample code (make sure to use the correct IP addresses and port):

    import socket
    import time
    
    host_addr = '000.000.000.00'
    host_port = 1234
    host = (host_addr, host_port)
    local_addr = '9.999.999.99'
    local_port = 1234
    local = (local_addr, local_port)
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.bind(local)
    print("Sending: 'Hello, UDP#1!")
    s.sendto("Hello, UDP#1!", host)
    time.sleep(1)
    print("Sending: 'Hello, UDP#2!")
    s.sendto("Hello, UDP#2!", host)
    data, address = s.recvfrom(1024)
    print(data)
    print(address)
    
    print("Sending: 'Hello, UDP#3!")
    s.sendto("Hello, UDP#3!", host)
    time.sleep(1)
    print("Sending: 'Hello, UDP#4!")
    s.sendto("Hello, UDP#4!", host)
    time.sleep(1)
    print("Sending: 'Hello, UDP#5!")
    s.sendto("Hello, UDP#5!", host)
    data, address = s.recvfrom(1024)
    print(data)
    print(address)
    
    print("Closing connection")
    s.close()
    
  2. Establish and test a UDP connection:

    1. Open a UDP socket and bind it to the UDP port that you want to use. Replace 1234 with the correct port number.

      AT#XSOCKET=1,2,1
      #XSOCKET: 2, 2, 1, 17
      OK
      
      AT#XBIND=1234
      OK
    2. Run the client_udp.py script to start sending data to the server.

    3. Start receiving and acknowledging the data. Replace example.com with the host name or IPv4 address of the UDP client and 1234 with the corresponding port.

      AT#XRECVFROM
      Hello, UDP#1!
      #XRECVFROM: 1, 13
      OK
      
      AT#XRECVFROM
      Hello, UDP#2!
      #XRECVFROM: 1, 13
      OK
      
      AT#XSENDTO="example.com",1234,1,"UDP1/2 received"
      #XSENDTO: 15
      OK
      
      AT#XRECVFROM
      Hello, UDP#3!
      #XRECVFROM: 1, 13
      OK
      
      AT#XRECVFROM
      Hello, UDP#4!
      #XRECVFROM: 1, 13
      OK
      
      AT#XRECVFROM
      Hello, UDP#5!
      #XRECVFROM: 1, 13
      OK
      
      AT#XSENDTO="example.com",1234,1,"UDP3/4/5 received"
      #XSENDTO: 17
      OK

      Note that you will get an error message if a UDP packet is lost. For example, this error indicates that a packet is lost in the downlink to the nRF9160 DK:

      AT#XRECVFROM
      #XSOCKET: -60
      ERROR
    4. Observe the output of the Python script:

      $ python client_udp.py
      
      Sending: 'Hello, UDP#1!
      Sending: 'Hello, UDP#2!
      UDP1/2 received
      ('000.000.000.00', 1234)
      Sending: 'Hello, UDP#3!
      Sending: 'Hello, UDP#4!
      Sending: 'Hello, UDP#5!
      UDP3/4/5 received
      ('000.000.000.00', 1234)
      Closing connection
      
    5. Close the socket.

      AT#XSOCKET=0
      #XSOCKET: 0, closed
      OK
  3. Test the UDP server with UDP proxy service (note that these commands are available only if CONFIG_SLM_UDP_PROXY is defined):

    1. Check the available values for the XUDPSVR command and create a UDP server. Replace 1234 with the correct port number.

      AT#XUDPSVR=?
      #XUDPSVR: (0, 1, 2),<port>,<sec_tag>
      OK
      
      AT#XUDPSVR=1,1234
      #XUDPSVR: 2 started
      OK
    2. Run the client_udp.py script to start sending data to the server.

    3. Observe that the server starts receiving data and acknowledge the data.

      #XUDPRECV: 1, 13
      Hello, UDP#1!
      #XUDPRECV: 1, 13
      Hello, UDP#2!
      
      AT#XUDPSEND=1,"UDP1/2 received"
      #XUDPSEND: 15
      OK
      
      #XUDPRECV: 1, 13
      Hello, UDP#3!
      #XUDPRECV: 1, 13
      Hello, UDP#4!
      #XUDPRECV: 1, 13
      Hello, UDP#5!
      
      AT#XUDPSEND=1,"UDP3/4/5 received"
      #XUDPSEND: 17
      OK
    4. Observe the output of the Python script:

      $ python client_udp.py
      
      Sending: 'Hello, UDP#1!
      Sending: 'Hello, UDP#2!
      UDP1/2 received
      ('000.000.000.00', 1234)
      Sending: 'Hello, UDP#3!
      Sending: 'Hello, UDP#4!
      Sending: 'Hello, UDP#5!
      UDP3/4/5 received
      ('000.000.000.00', 1234)
      Closing connection
      
    5. Close the socket.

      AT#XUDPSVR=0
      #XUDPSVR: stopped
      OK
  4. Test the UDP server with UDP proxy service in data mode (note that these commands are available only if CONFIG_SLM_UDP_PROXY is defined):

    1. Create a UDP server and read information about the current state. Replace 1234 with the correct port number.

      AT#XUDPSVR=2,1234
      #XUDPSVR: 1 started
      OK
      
      AT#XUDPSVR?
      #XUDPSVR: 1, 1
      OK
    2. Run the client_udp.py script to start sending data to the server.

    3. Observe that the server starts receiving data. Acknowledge the received data.

      Hello, UDP#1!Hello, UDP#2!UDP1/2 received
      Hello, UDP#3!Hello, UDP#4!Hello, UDP#5!UDP3/4/5 received
    4. Observe the output of the Python script:

      $ python client_udp.py
      
      Sending: 'Hello, UDP#1!
      Sending: 'Hello, UDP#2!
      UDP1/2 received
      ('000.000.000.00', 1234)
      Sending: 'Hello, UDP#3!
      Sending: 'Hello, UDP#4!
      Sending: 'Hello, UDP#5!
      UDP3/4/5 received
      ('000.000.000.00', 1234)
      Closing connection
      
    5. Stop the server.

      AT#XUDPSVR=0
      #XUDPSVR: stopped
      OK
TLS server

The TLS server role is currently not supported.

AT#XSOCKET=1,1,1,16842753
#XSOCKET: (D)TLS Server not supported
ERROR

AT#XTCPSVR=1,3443,16842753
#XTCPSVR: TLS Server not supported
ERROR
DTLS server

The DTLS server role is currently not supported (modem limitation).

AT#XSOCKET=1,2,1,16842755
#XSOCKET: (D)TLS Server not supported
ERROR
DNS lookup
  1. Look up the IP address for a host name.

    AT#XGETADDRINFO="www.google.com"
    #XGETADDRINFO: 172.217.174.100
    OK
  2. Observe that you cannot look up the host name for an IP address.

    AT#XGETADDRINFO="172.217.174.100"
    ERROR
Socket options

After opening a client-role socket, you can configure various options.

  1. Check the available values for the XSOCKETOPT command.

    AT#XSOCKETOPT=?
    #XSOCKETOPT: (0, 1), <name>, <value>
    OK
  2. Open a client socket.

    AT#XSOCKET=1,1,0
    #XSOCKET: 2, 1, 0, 6
    OK
  3. Test to set and get socket options. Note that not all options are supported.

    AT#XSOCKETOPT=1,20,30
    OK
    
    AT#XSOCKETOPT=0,20
    ERROR  // to be investigated
    
    AT#XSOCKETOPT=0,2
    #XSOCKETOPT: ignored
    OK
    
    AT#XSOCKETOPT=1,2,1
    #XSOCKETOPT: ignored
    OK
    
    AT#XSOCKETOPT=0,61
    #XSOCKETOPT: not supported
    OK
    
    AT#XSOCKETOPT=1,61,30
    #XSOCKETOPT: not supported
    OK

Testing ICMP AT commands

Complete the following steps to test the functionality provided by the ICMP AT Commands:

  1. Ping a remote host, for example, www.google.com.

    AT#XPING="www.google.com",45,5000,5,1000
    #XPING: 0.637
    #XPING: 0.585
    #XPING: 0.598
    #XPING: 0.598
    #XPING: 0.599
    #XPING: average 0.603
    OK
  2. Ping a remote IP address, for example, 172.217.174.100.

    AT#XPING="172.217.174.100",45,5000,5,1000
    #XPING: 0.873
    #XPING: 0.576
    #XPING: 0.599
    #XPING: 0.623
    #XPING: 0.577
    #XPING: average 0.650
    OK

Testing FTP AT commands

Before you test the FTP AT commands, check the setting of the CONFIG_FTP_CLIENT_KEEPALIVE_TIME option. By default, the FTP client library keeps the connection to the FTP server alive for 60 seconds, but you can change the duration or turn KEEPALIVE off by setting CONFIG_FTP_CLIENT_KEEPALIVE_TIME to 0.

The FTP client behavior depends on the FTP server that is used for testing. Complete the following steps to test the functionality provided by the FTP AT Commands with two example servers:

  1. Test an FTP connection to “speedtest.tele2.net”.

    This server supports only anonymous login. Files must be uploaded to a given folder and will be deleted immediately. It is not possible to create, rename, or delete folders or rename files.

    1. Connect to the FTP server, check the status, and change the transfer mode. Then disconnect.

      AT#XFTP="open",,,"speedtest.tele2.net"
      220 (vsFTPd 3.0.3)
      200 Always in UTF8 mode.
      331 Please specify the password.
      230 Login successful.
      OK
      
      AT#XFTP="status"
      215 UNIX Type: L8
      211-FTP server status:
           Connected to ::ffff:202.238.218.44
           Logged in as ftp
           TYPE: ASCII
           No session bandwidth limit
           Session timeout in seconds is 300
           Control connection is plain text
           Data connections will be plain text
           At session startup, client count was 38
           vsFTPd 3.0.3 - secure, fast, stable
      211 End of status
      OK
      
      AT#XFTP="ascii"
      200 Switching to ASCII mode.
      OK
      
      AT#XFTP="binary"
      200 Switching to Binary mode.
      OK
      
      AT#XFTP="close"
      221 Goodbye.
      OK
    2. Connect to the FTP server and retrieve information about the existing files and folders.

      AT#XFTP="open",,,"speedtest.tele2.net"
      220 (vsFTPd 3.0.3)
      200 Always in UTF8 mode.
      331 Please specify the password.
      230 Login successful.
      OK
      
      AT#XFTP="pwd"
      257 "/" is the current directory
      OK
      
      AT#XFTP="ls"
      227 Entering Passive Mode (90,130,70,73,103,35).
      1000GB.zip
      100GB.zip
      100KB.zip
      [...]
      5MB.zip
      upload
      150 Here comes the directory listing.
      226 Directory send OK.
      OK
      
      AT#XFTP="ls","-l"
      227 Entering Passive Mode (90,130,70,73,94,158).
      150 Here comes the directory listing.
      -rw-r--r--    1 0        0        1073741824000 Feb 19  2016 1000GB.zip
      -rw-r--r--    1 0        0        107374182400 Feb 19  2016 100GB.zip
      -rw-r--r--    1 0        0          102400 Feb 19  2016 100KB.zip
      -rw-r--r--    1 0        0        104857600 Feb 19  2016 100MB.zip
      [...]
      -rw-r--r--    1 0        0         5242880 Feb 19  2016 5MB.zip
      drwxr-xr-x    2 105      108        561152 Apr 30 02:30 upload
      226 Directory send OK.
      OK
      
      AT#XFTP="ls","-l","upload"
      227 Entering Passive Mode (90,130,70,73,86,44).
      150 Here comes the directory listing.
      -rw-------    1 105      108      57272385 Apr 30 02:29 10MB.zip
      -rw-------    1 105      108        119972 Apr 30 02:30 14qj36kc9esslej6porartkjks.txt
      [...]
      -rw-------    1 105      108         32352 Apr 30 02:30 upload_file.txt
      226 Directory send OK.
      OK
      
      AT#XFTP="cd","upload"
      250 Directory successfully changed.
      OK
      
      AT#XFTP="pwd"
      257 "/upload" is the current directory
      OK
      
      AT#XFTP="ls","-l"
      227 Entering Passive Mode (90,130,70,73,113,191).
      150 Here comes the directory listing.
      -rw-------    1 105      108      57272385 Apr 30 02:29 10MB.zip
      -rw-------    1 105      108        294236 Apr 30 02:31 1MB.zip
      [...]
      -rw-------    1 105      108        838960 Apr 30 02:31 upload_file.txt
      226 Directory send OK.
      OK
      
      AT#XFTP="cd", ".."
      250 Directory successfully changed.
      OK
      
      AT#XFTP="pwd"
      257 "/" is the current directory
      OK
      
      AT#XFTP="ls","-l"
      227 Entering Passive Mode (90,130,70,73,90,43).
      150 Here comes the directory listing.
      -rw-r--r--    1 0        0        1073741824000 Feb 19  2016 1000GB.zip
      -rw-r--r--    1 0        0        107374182400 Feb 19  2016 100GB.zip
      -rw-r--r--    1 0        0          102400 Feb 19  2016 100KB.zip
      [...]
      -rw-r--r--    1 0        0         5242880 Feb 19  2016 5MB.zip
      drwxr-xr-x    2 105      108        561152 Apr 30 02:31 upload
      226 Directory send OK.
      OK
      
      AT#XFTP="ls","-l 1KB.zip"
      227 Entering Passive Mode (90,130,70,73,106,84).
      150 Here comes the directory listing.
      -rw-r--r--    1 0        0            1024 Feb 19  2016 1KB.zip
      226 Directory send OK.
      OK
    3. Switch to binary transfer mode and download a file from the server.

      AT#XFTP="binary"
      200 Switching to Binary mode.
      OK
      
      AT#XFTP="get","1KB.zip"
      227 Entering Passive Mode (90,130,70,73,84,29).
      
      00000000000000000000000000[...]000000000000
      226 Transfer complete.
      OK
    4. Navigate to the upload folder, switch to binary transfer mode, and create a binary file with the content “DEADBEEF”.

      AT#XFTP="cd","upload"
      250 Directory successfully changed.
      OK
      
      AT#XFTP="binary"
      200 Switching to Binary mode.
      OK
      
      AT#XFTP="put","upload.bin",0,"DEADBEEF"
      227 Entering Passive Mode (90,130,70,73,114,150).
      150 Ok to send data.
      226 Transfer complete.
      OK
    5. Switch to ASCII transfer mode and create a text file with the content “TEXTDATA”.

      AT#XFTP="ascii"
      200 Switching to ASCII mode.
      OK
      
      AT#XFTP="put","upload.txt",1,"TEXTDATA"
      227 Entering Passive Mode (90,130,70,73,99,84).
      150 Ok to send data.
      226 Transfer complete.
      OK
    6. Disconnect from the server.

      AT#XFTP="close"
      221 Goodbye.
      OK
  2. Test an FTP connection to “ftp.dlptest.com”.

    This server does not support anonymous login. Go to DLPTest.com to get the latest login information. After login on, you can create and remove folders and files, rename files, and upload files.

    1. Connect to the FTP server and check the status. Replace user and password with the login information from DLPTest.com.

      AT#XFTP="open","user","password","ftp.dlptest.com"
      220-#########################################################
      220-Please upload your web files to the public_html directory.
      220-Note that letters are case sensitive.
      220-#########################################################
      220 This is a private system - No anonymous login
      200 OK, UTF-8 enabled
      331 User user OK. Password required
      230-Your bandwidth usage is restricted
      230 OK. Current restricted directory is /
      OK
      
      AT#XFTP="status"
      215 UNIX Type: L8
      211 https://www.pureftpd.org/
      OK
    2. Retrieve information about the existing files and folders.

      AT#XFTP="pwd"
      257 "/" is your current location
      OK
      
      AT#XFTP="ls"
      227 Entering Passive Mode (35,209,241,59,135,181)
      150 Accepted data connection
      226-Options: -a
      226 42 matches total
      OK
      .
      ..
      1_2596384601376578508_17-9ULspeedtest.upt
      1_603281663034123496_17-9ULspeedtest.upt
      [...]
      aa_.rar
      write to File.txt
    3. Create a folder and enter it.

      AT#XFTP="mkdir", "newfolder"
      257 "newfolder" : The directory was successfully created
      OK
      
      AT#XFTP="ls","-l","newfolder"
      227 Entering Passive Mode (35,209,241,59,135,134)
      150 Accepted data connection
      226-Options: -a -l
      226 2 matches total
      OK
      drwxr-xr-x    2 dlptest9   dlptest9         4096 Apr 29 19:53 .
      drwxr-xr-x    3 dlptest9   dlptest9        57344 Apr 29 19:53 ..
      +CEREG: 1,"1285","02EF8210",7
      
      AT#XFTP="cd","newfolder"
      250 OK. Current directory is /newfolder
      OK
    4. Switch to binary transfer mode and create a binary file with the content “DEADBEEF”.

      AT#XFTP="binary"
      200 TYPE is now 8-bit binary
      OK
      
      AT#XFTP="put","upload.bin",0,"DEADBEEF"
      227 Entering Passive Mode (35,209,241,59,135,182)
      150 Accepted data connection
      226-File successfully transferred
      226 0.013 seconds (measured here), 310.20 bytes per second
      OK
      
      AT#XFTP="ls","-l","upload.bin"
      227 Entering Passive Mode (35,209,241,59,135,146)
      150 Accepted data connection
      226-Options: -a -l
      226 1 matches total
      OK
      -rw-r--r--    1 dlptest9   dlptest9            4 Apr 29 19:54 upload.bin
    5. Rename the file.

      AT#XFTP="rename","upload.bin","uploaded.bin"
      350 RNFR accepted - file exists, ready for destination
      250 File successfully renamed or moved
      OK
      
      AT#XFTP="ls","-l","uploaded.bin"
      227 Entering Passive Mode (35,209,241,59,135,111)
      150 Accepted data connection
      -rw-r--r--    1 dlptest9   dlptest9            4 Apr 29 19:54 uploaded.bin
      226-Options: -a -l
      226 1 matches total
      OK
    6. Switch to ASCII transfer mode and create a text file with the content “line #1\r\n”.

      AT#XFTP="ascii"
      200 TYPE is now ASCII
      OK
      
      AT#XFTP="put","upload.txt",1,"line #1\r\n"
      227 Entering Passive Mode (35,209,241,59,135,136)
      150 Accepted data connection
      226-File successfully transferred
      226 0.013 seconds (measured here), 0.82 Kbytes per second
      OK
      
      AT#XFTP="ls","-l upload.txt"
      227 Entering Passive Mode (35,209,241,59,135,166)
      150 Accepted data connection
      226-Options: -a -l
      226 1 matches total
      OK
      -rw-r--r--    1 dlptest9   dlptest9           11 Apr 29 19:56 upload.txt
    7. Rename the file.

      AT#XFTP="rename","upload.txt","uploaded.txt"
      350 RNFR accepted - file exists, ready for destination
      250 File successfully renamed or moved
      OK
      
      AT#XFTP="ls","-l uploaded.txt"
      227 Entering Passive Mode (35,209,241,59,135,213)
      200 Zzz...  // (KEEPALIVE response)
      150 Accepted data connection
      226-Options: -a -l
      226 1 matches total
      OK
      -rw-r--r--    1 dlptest9   dlptest9           11 Apr 29 19:56 uploaded.txt
      +CEREG: 1,"1285","02EF8200",7
    8. Delete the files and the folder that you created.

      AT#XFTP="delete","uploaded.bin"
      250 Deleted uploaded.bin
      OK
      
      AT#XFTP="delete","uploaded.txt"
      250 Deleted uploaded.txt
      OK
      
      AT#XFTP="cd", ".."
      250 OK. Current directory is /
      OK
      
      AT#XFTP="rmdir", "newfolder"
      250 The directory was successfully removed
      OK
    9. Disconnect from the server.

      AT#XFTP="close"
      221-Goodbye. You uploaded 1 and downloaded 0 kbytes.
      221 Logout.
      OK

Dependencies

This application uses the following nRF Connect SDK libraries:

It uses the following nrfxlib libraries:

In addition, it uses the following samples: