Menu

Expand
Rate this page:

Get Started with Super SIM IP Commands and the Pycom GPy

IP Commands is a new Super SIM feature that allows your cloud to communicate with your IoT devices by exchanging IP/UDP messages. You can use IP Commands to send server-initiated IP messages from your cloud to your Super SIM-connected devices. The best part is that you don’t actually need to know a device’s IP address — Twilio will handle that for you. Nor do you need to maintain a persistent connection between a device and your server.

You can think of IP Commands as a lightweight alternative to using a Virtual Private Network (VPN) to reach a device from your cloud and exchange information.

This information is transferred in the form of User Datagram Protocol (UDP) messages. UDP provides basic, ‘fire and forget’ data exchange: there’s no connection established between sender and receiver — and no guarantee that the message will be delivered. This simplicity makes UDP ideal for lightweight IoT applications: it’s a great way to send commands (“change the air con setting to 40C”) to a connected device. Such commands might come from your cloud, or from your app running on an end-user’s mobile device. They would be more structured than the colloquial example shown above, and completely flexible: your application, not the transport, defines the command-response interaction.

Cellular IoT devices like Pycom’s GPy which have their own operating system and run a single application through an interpreter — in the GPy’s case, MicroPython — particularly benefit from IP commands because such devices don’t expose SMS functionality to the application, or make interacting with the on-board cellular module via AT commands difficult. Instead, you can use their integrated networking APIs to establish data connections over which IP commands can be transferred. This short guide will show you how this can be achieved.

Super SIM IP Commands Pycom GPy and Expansion Board

The GPy includes a Sequans Monarch Cat-M1/NB-IoT cellular module. Super SIM doesn’t currently support NB-IoT, so this guide focuses on Cat-M1 connectivity. While you can work with the GPy alone, we recommend connecting it to a Pycom Expansion Board, as shown above, which provides a USB port for easy connection to your computer.

If you’d like to try IP Commands with different hardware, we have a tutorial that focuses on the Raspberry Pi 4, and which also makes use of IP Commands to send instructions to the device and receive data back. You can check it out here.

We also have an IP Commands tutorial for the Raspberry Pi Pico microcontroller board.

This guide requires a configured Super SIM. If you haven’t set up your Super SIM in the Console, please do so now. The Super SIM First Steps guide has help if you need it.

Your GPy may not include the latest firmware, so we recommend you visit Pycom’s firmware update page to find out about the latest firmware release and how to install it on your device.

Pycom strongly recommends that you don’t make use of the GPy’s LTE functionality without an antenna attached. It says this can “seriously damage” the device. Who are we to argue? Please make sure you follow Pycom’s guidance.

The GPy does not ship with an antenna, so make sure you order one when you buy your GPy.

To send or receive messages, you need to set up the GPy’s Cat-M1 module for UDP communication.

  1. First, turn the GPy over and slip your Super SIM label side up into the device’s nano SIM slot:
    Slot a Super SIM into the GPy
  2. Fit the GPy to the Expansion Board:
    Fit the GPy to the Expansion Board

    Make sure they are correctly aligned: match the RST pin on the Board to the one on the GPy, which is the the one closest to the reset button:
    Check the alignment
  3. Connect a Cat-M1 antenna to the GPy:
    Fit an antenna
  4. Connect the USB cable to the Expansion Board and to your computer.
  5. If you’re using a Mac, open a terminal and enter ls /dev/cu*. You should see a line like:
    crw-rw-rw- 1 root wheel 9, 3 Jul 20 11:19 /dev/cu.usbmodemPyeb13b91

    This is the GPy’s device file, which we’ll use in the next step.
    Linux users should use /dev/ttyACM0. You may need to ensure you have access to the serial port: on most distributions this can be done by adding your user account to the dialout user group.
  6. You’ll use a command-line serial console tool called Minicom to communicate with the GPy’s application environment. If you would prefer to use an alternative tool, such as Screen, that’s fine, but it may have a slightly different device-selection procedure than the one outlined here. Install Minicom using your operating system’s package manager. On a Linux computer, or a Windows machine running Windows Subsystem for Linux, that will be apt, rpm, dpkg, or similar, e.g., sudo apt install minicom.
    On a Mac, make use of brew with the command: brew install minicom.
  7. Enter minicom -D <GPY_DEVICE_FILE> to open a connection to the module. If Minicom posts an error indicating that the device is inaccessible, please check that you’ve connected the GPy correctly.

2. Enter some Python code

In Minicom, hit Ctrl-C to break to the Python REPL. You won’t use the REPL directly, but it provides a way to enter large blocks of MicroPython code easily. Now hit Ctrl-E. This makes MicroPython ready to accept a full Python program pasted in. Click on the button at the top right of the following code to copy it and paste it into Minicom. The copy button will appear when you mouse over the code. When you’ve pasted the code, hit Ctrl-D.

Now jump past the code to continue with the tutorial.

import time
import sys
import pycom
import usocket as socket
from network import LTE

# Functions

'''
Set the GPy LED's color.
'pycom.rgbled()' takes RGB value as an integer eg. 0x302000,
but we supply a tuple with the colour the second value
'''
def set_led_colour(new_color):
    pycom.rgbled(new_color[1])

'''
Prepare and return a new socket
'''
def get_socket():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    s.bind(("", 6969))
    s.settimeout(1.0)
    return s

def do_attach(lte):
    # Attach using the Super SIM APN
    try:
        lte.attach(band=20, apn="super", cid=1)
        flash = True
        while not lte.isattached():
            time.sleep(0.5)
            flash = not flash
            colour = RED if flash else CLEAR
            set_led_colour(colour)
    except OSError as msg:
        return False
    # Attached...
    set_led_colour(YELLOW)
    return True

def do_connect(lte):
    lte.connect(cid=1)
    flash = True
    while not lte.isconnected():
        time.sleep(0.5)
        flash = not flash
        colour = YELLOW if flash else CLEAR
    set_led_colour(GREEN)
    return get_socket()

'''
LTE connection loss callback
'''
def lte_handler(arg):
    # Just in case
    udp_socket.close()

    # Tell the user
    set_led_colour(RED)

    # Check event
    if arg.events() & LTE.EVENT_BREAK:
        print("UART break signal")

# Color constants
RED     = ("RED",     0x300000)
GREEN   = ("GREEN",   0x003000)
BLUE    = ("BLUE",    0x000030)
YELLOW  = ("YELLOW",  0x302000)
MAGENTA = ("MAGENTA", 0x300030)
CYAN    = ("CYAN",    0x002030)
WHITE   = ("WHITE",   0x303030)
CLEAR   = ("CLEAR",   0x000000)

# Array the colors
colors = [RED, GREEN, BLUE, YELLOW, MAGENTA, CYAN, WHITE, CLEAR]

# Set the timers
seconds = 0
minutes = 0
buffer_size = 256
udp_socket = None

# Turn of the default LED flash
pycom.heartbeat(False)

# Instantiate the LTE object
set_led_colour(RED)
lte = LTE()
lte.init()
lte.lte_callback(LTE.EVENT_BREAK, lte_handler)

# Attach to LTE-M...
if do_attach(lte) is False:
    print("Could not attach to the network... restarting")
    machine.reset()

# Establish a data connection...
udp_socket = do_connect(lte)
if udp_socket is not None:
    print("Connected, listening for IP commands...")

    # Loop to listen for messages
    while True:
        # Check for data - this will timeout after 1s
        try:
            message, address = udp_socket.recvfrom(buffer_size)
            new_color = message.decode("utf-8")
            changed = False
            for color in colors:
                if color[0] == new_color:
                    set_led_colour(color)
                    changed = True
            if not changed:
                msg = "Bad color value received:"
            else:
                msg = "Color received:"
            print(msg, new_color)
        except OSError as msg:
            pass

        seconds += 1
        if seconds % 600 == 0:
            # After approx. 10 minutes, stop listening
            udp_socket.close()
            lte.deinit()
            set_led_colour(CLEAR)
            print("All done -- exiting")
            break
else:
    print("ERROR -- could not open socket")

MicroPython will check the code and, if it’s free of syntax errors, run it. You should see the GPy’s RGB LED turn red and then flash as the device attempts to connect to the network. When it has done so, its LED goes yellow, and then green when it has a data connection established. You’ll see Connected, listening for IP commands... in Minicom.

The first time you power up the GPy, it can take some time for the on-board cellular module to attach to the network. Please be patient and let it do so.

The code that’s running not only sets up a network connection, it also primes the GPy to open a UDP socket and listen for incoming commands. What command can you send it? A valid color name — they’re set at line 62 in the listing — that the GPy will use to set the color of its LED.

3. Send an IP Command to the device

  1. Open a second terminal or a new terminal tab on your computer.
  2. Send a color using the curl tool as follows:
    curl -X POST https://supersim.twilio.com/v1/IpCommands \
      --data-urlencode 'Sim=<YOUR_SIM_NAME_OR_SID>' \
      --data-urlencode Payload=BLUE \
      --data-urlencode PayloadType=text \
      --data-urlencode DevicePort=6969 \
      -u <YOUR_ACCOUNT_SID>:<YOUR_AUTH_TOKEN>
    Copy and paste the curl command to the command line then edit it to fill in the identifier of the Super SIM you’re using (you can get this from the Console if you don’t have it handy), and your account credentials (also available from the Console). The IP command is the value of the payload parameter.

The response, posted to the terminal by curl, will be a JSON string. It will include a number of fields, but look out for these two:

"status": "queued", 
"direction": "to_sim"

As you can see, the message’s status is queued: it’s in Twilio’s message queue waiting to be sent. When the IP Command leaves the Twilio Mobile Core for the network the device is attached to, its status will become sent. Later on, you’ll use a webhook, which you’ll set up in the next section, to receive notifications about message status changes as they happen. For details of the possible status values you may see, take a look at the API documentation.

4. See the IP Command’s effect on the device

Has the GPy’s LED changed color? It will change blue if the IP Command was received. The code will print a note in Minicom if it didn’t recognize the color value you sent.

Try sending some further messages with different colors. Send some invalid color names.

In a real-world application the message would come from your server, not be sent manually, and your device-side application would be actively checking for incoming messages and parsing any that arrive, but the demo gives you a picture of the flow. IP Commands also supports binary data. To send information in this form, you would change the PayloadType parameter in the message-send code to "binary".

However, IP Commands isn’t a one-way route — let’s see how messages can travel in the opposite direction, from the device.

Receive an IP Command from the device

The IP Commands API provides a specific IP address, 100.64.0.1, to which all IP Commands, from every device are sent. Twilio uses a little bit of magic to streamline the relay of your messages to your cloud. How does it know where to send them? You specify a webhook address.

Super SIMs are organized into Fleets: groups of SIMs that have common settings, such as which networks they are able to connect to and whether they can make use of cellular data services. Fleets are represented in the Super SIM API by Fleet resources, and IP Commands adds a property to each Fleet resource in which you can store your IP Commands webhook address.

So before we can send a message, we need to set up a webhook target URL and add that to your Super SIM’s Fleet.

1. Set up a webhook target

Beeceptor is a handy service for testing webhooks. It’s designed for developing and testing APIs of your own, and offers free mock servers — virtual endpoints that can receive webhook calls. Let’s set one up to receive messages from the device.

  1. In a web browser tab, go to Beeceptor.
  2. Enter an endpoint name and click Create Endpoint:
    The Beeceptor home page
  3. On the screen that appears next, click on the upper of the two clipboard icons to copy the endpoint URL:
    Your endpoint in Beeceptor
  4. Keep the tab open.

2. Update your Super SIM’s Fleet

Now you update your Super SIM’s Fleet to add an IP Commands webhook. You can do this with the API, but we’ll use the Console for this demo.

  1. Open a second web browser tab and log into the Twilio Console.
  2. Go to IoT > Super SIM > Fleets and select the Fleet containing the Super SIM you are using.
  3. Scroll down to IP Commands Callback URL and paste in your webhook URL from the previous section. By default, webhooks are triggered with a POST request. Leave it unchanged for now, but if you need to use another method for your own application, you can change it later.
  4. Click Save.
  5. Close the tab if you like.

3. Send a message

To add message sending to the device code, you can add following function:

'''
Send a Super SIM IP Command via the specified socket.
'''
def send_ip_cmd(sock, cmd):
    print("Sending",cmd)
    target = ("100.64.0.1", 6969)
    _ = sock.sendto(cmd.encode(), target)

This gets called by adding this to the end of the code:

    if seconds % 60 == 0:
        # Every minute, send a message
        minutes += 1
        send_ip_cmd(udp_socket, "Uptime minute {}".format(minutes))

Here’s the complete listing, which you should copy and then paste into MicroPython via Minicom as you did before. Hit Ctrl-F to reset the GPy, then when the >>> prompt appera, hit Ctrl-E to enter paste mode. When you’ve pasted in the code, hit Ctrl-D to run it:

import time
import sys
import pycom
import machine
import usocket as socket
from network import LTE

# Functions

'''
Set the GPy LED's color.
'pycom.rgbled()' takes RGB value as an integer eg. 0x302000,
but we supply a tuple with the colour the second value
'''
def set_led_colour(new_color):
    pycom.rgbled(new_color[1])

'''
Send a Super SIM IP Command via the specified socket.
'''
def send_ip_cmd(sock, cmd):
    print("Sending",cmd)
    target = ("100.64.0.1", 6969)
    _ = sock.sendto(cmd.encode(), target)

'''
Prepare and return a new socket
'''
def get_socket():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    s.bind(("", 6969))
    s.settimeout(1.0)
    return s

def do_attach(lte):
    # Attach using the Super SIM APN
    try:
        lte.attach(band=20, apn="super", cid=1)
        flash = True
        while not lte.isattached():
            time.sleep(0.5)
            flash = not flash
            colour = RED if flash else CLEAR
            set_led_colour(colour)
    except OSError as msg:
        return False
    # Attached...
    set_led_colour(YELLOW)
    return True

def do_connect(lte):
    lte.connect(cid=1)
    flash = True
    while not lte.isconnected():
        time.sleep(0.5)
        flash = not flash
        colour = YELLOW if flash else CLEAR
    set_led_colour(GREEN)
    return get_socket()

'''
LTE connection loss callback
'''
def lte_handler(arg):
    # Just in case
    udp_socket.close()

    # Tell the user
    set_led_colour(RED)

    # Check event
    if arg.events() & LTE.EVENT_BREAK:
        print("UART break signal")

# Color constants
RED     = ("RED",     0x300000)
GREEN   = ("GREEN",   0x003000)
BLUE    = ("BLUE",    0x000030)
YELLOW  = ("YELLOW",  0x302000)
MAGENTA = ("MAGENTA", 0x300030)
CYAN    = ("CYAN",    0x002030)
WHITE   = ("WHITE",   0x303030)
CLEAR   = ("CLEAR",   0x00)

# Array the colors
colors = [RED, GREEN, BLUE, YELLOW, MAGENTA, CYAN, WHITE, CLEAR]

# Set the timers
seconds = 0
minutes = 0
buffer_size = 1024
udp_socket = None

# Turn of the default LED flash
pycom.heartbeat(False)

# Instantiate the LTE object
set_led_colour(RED)
lte = LTE()
lte.init()
lte.lte_callback(LTE.EVENT_BREAK, lte_handler)

# Attach to LTE-M...
if do_attach(lte) is False:
    print("Could not attach to the network... restarting")
    machine.reset()

# Establish a data connection...
udp_socket = do_connect(lte)
if udp_socket is not None:
    print("Connected, listening for IP commands...")

    # Loop to listen for messages
    while True:
        # Check for data - this will timeout after 1s
        try:
            message, address = udp_socket.recvfrom(buffer_size)
            new_color = message.decode("utf-8")
            changed = False
            for color in colors:
                if color[0] == new_color:
                    set_led_colour(color)
                    changed = True
            if not changed:
                msg = "Bad color value received:"
            else:
                msg = "Color received:"
            print(msg, new_color)
        except OSError as msg:
            pass

        seconds += 1
        if seconds % 600 == 0:
            # After approx. 10 minutes, bail
            udp_socket.close()
            lte.deinit()
            set_led_colour(CLEAR)
            print("All done -- exiting")
            break

        if seconds % 60 == 0:
            # Every minute, send a message
            minutes += 1
            send_ip_cmd(udp_socket, "Uptime minute {}".format(minutes))
else:
    print("ERROR -- could not open socket")

4. Read the message

Jump back to the Beeceptor tab in the browser. You should see — or will shortly see — the endpoint has received a POST request. Click on it to see the request body, then on the JSON icon, {:}, to view the data more clearly.

Unlike messages sent to the device, which can be text or binary, messages that are sent from the device are always binary. The string you entered has been base64 encoded, so it’ll need decoding before you can read it. Look for the line beginning Payload= and copy the characters that appear after it, up until the end of the line. It’ll look something like this:

bm90IGEgcmVhbCBtZXNzYWdlCg==

Switch to a spare terminal and enter:

echo <BASE64_ENCODED_STRING> | base64 -d
making sure you paste the text you copied between the echo and the | symbol as indicated. You’ll be presented with the message you sent from the device in the previous section: Uptime minute 1.

Monitor IP Command transmission

The webhook URL you just put in place was set up to receive IP Commands from the device. You can also use it in a tutorial context for monitoring messages being sent to the device. Use the same technique you applied in the Send IP Commands to the device section, above, but this time add the following extra command to the curl call, replacing <YOUR_WEBHOOK_URL> with your Beeceptor endpoint.

--data-urlencode 'CallbackUrl=<YOUR_WEBHOOK_URL>'

Now you’ll receive a series of notification messages as the IP Command’s status moves from queued to sent. For details of the possible status values you may see, take a look at the API documentation.

Next steps

You’ve set up a Pycom GPy to send and receive UDP messages over a data connection, then you’ve sent messages to the device and back again, all through Twilio Super SIM’s IP Commands API.

You can try sending some alternative messages, including some binary data.

Try using IP Commands to toggle GPIO pins so the GPy can begin to control things. Create a web page to call the API and trigger the commands.

You can use a tool like Ampy or rshell to transfer your MicroPython code to the GPy as a file. It will then run automatically when the GPy is reset so you don’t need to use paste mode. You need to name the file main.py. Check out the tools’ Read Mes for more details.

IP Command Resources are persisted for 30 days, so you can check your send and receive histories at any time. For example, a GET request made to https://supersim.twilio.com/v1/IpCommands will fetch all existing resources for inspection. If you have the SID of a specific Command’s resource, you can add it as a path value to the endpoint above. Try it now.

The next stage, of course, is to build a device-side app that listens for a variety of commands, parses them and triggers actions accordingly. You may also want to create a server app that’s able to request information from devices: it sends a request command which causes the device to send a second, data-bearing message back. Or you might code up a mobile app that uses IP Commands to control the device remotely.

We can’t wait to see what you build with Super SIM IP Commands!

Rate this page:

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd by visiting Twilio's Community Forums or browsing the Twilio tag on Stack Overflow.

Thank you for your feedback!

We are always striving to improve our documentation quality, and your feedback is valuable to us. Please select the reason(s) for your feedback or provide additional information about how we can improve:

Sending your feedback...
🎉 Thank you for your feedback!
Something went wrong. Please try again.

Thanks for your feedback!

Refer us and get $10 in 3 simple steps!

Step 1

Get link

Get a free personal referral link here

Step 2

Give $10

Your user signs up and upgrade using link

Step 3

Get $10

1,250 free SMSes
OR 1,000 free voice mins
OR 12,000 chats
OR more