Important notice: This post is about integrating the legacy Nabto 4/Micro (uNabto) platform which is no longer supported for new designs. Instead, it is highly recommended to look at the modern Nabto 5/Edge platform. CC3200 is not yet supported by Nabto 5/Edge – but you can follow the general integration guide for integrating Nabto 5/Edge to new platforms, including a step-by-step test-harness to simplify the integration. Also, take a look at the embedded platforms currently supported by Nabto 5/Edge.

Texas Instrument’s CC3200 is a single-chip microcontroller unit with built-in Wi-Fi connectivity, created for the Internet of Things. It can run the FreeRTOS operating system and provides a hardware encryption engine. Sounds interesting? It did to us! So we created a demo that is capable of streaming two-way audio between the CC3200 and an Android App using our uNabto framework. Why do you need Nabto for this? Because it solves all the router and firewall hassle for you: all you need to connect to the device is a unique Device ID!

What you need

Just hook up the two boards as described in the Audio BoosterPack User Guide provided by TI.

How the Nabto platform works

How does the Nabto platform work exactly? The drawing below gives a brief overview. Your CC3200 represents the Device running the uNabto server. As soon as it connects to the internet it identifies itself at the Nabto Basestation, using its unique ID. If a Client (i.e. the Android App in this demo) wants to connect to the CC3200, a connect request with the ID is sent to the Basestation, and a direct connection to the device is established.


Get more information on the Nabto Cloud Console and the Client/Device SDKs at

The uNabto Platform Adapter:

The uNabto Platform Adapter is a small component that abstracts the Native Platforms network and time functionality. The Platform Adapter is part of the uNabto server.

The uNabto server is divided into two layers:

  • The uNabto framework (uNabto SDK)
  • The uNabto Platform Adapter abstraction layer between the framework and the Native Platform


To run the uNabto server on the CC3200, we only need to implement the uNabto Platform Adapter (for details see the TEN023 Nabto device SDK guide). The CC3200 adapter is divided into the following files:

  • unabto_config.h: Basic uNabto configuration
  • unabto_platform_types.h: Define all necessary uNabto types
  • unabto_platform.h: Platform specific ad-hoc functions
  • unabto_adapter_network.c: Init, close, read and write functionality for network data
  • unabto_adapter_time.c: Time functions
  • unabto_adapter_dns.c: DNS resolving
  • unabto_adapter_random.c: Random generator
  • unabto_adapter_crypto.c: CC3200 hardware encryption

If you are interested in how the platform adapter is implemented in detail, check the adapter files on GitHub.

The Device Application

Info: The following describes the audio demo application (‘audio’ branch). A more generic and straightforward example of using streaming to echo data is maintained in the ‘master’ branch of our CC3200 GitHub repository.

The uNabto server is running in its own task implemented in unabto_task.c. After waiting for the network connection being established in another task, the uNabto server is initialized with basic settings as well as the unique Device ID and pre-shared encryption key from  Then, the server continuously handles incoming network events and checks for available recorded audio to send to the client.

void UNabto(void* pvParameters) {
    // device id and key from
    const char* nabtoId = "<DEVICE ID>";
    const char* presharedKey = "<KEY>";

    // Initialize uNabto
    nabto_main_setup* nms = unabto_init_context();
    nms->ipAddress = g_uiIpAddress;
    nms->id = nabtoId;
    nms->secureAttach = 1;
    nms->secureData = 1;
    nms->cryptoSuite = CRYPT_W_AES_CBC_HMAC_SHA256;

    const char* p;
    unsigned char* up;
    for (p = presharedKey, up = nms->presharedKey; *p; p += 2, ++up) {
        *up = hctoi(p[0]) * 16 + hctoi(p[1]);  // hex string to byte array

    while ((!IS_CONNECTED(g_ulStatus)) || (!IS_IP_ACQUIRED(g_ulStatus))) {



    while (true) {

The actual audio streaming code is in stream_audio.c. The unabto_stream_event() function handles all incoming streaming events. Once a Nabto stream connection is established, the device is waiting for a stream command. In this case, there is only the command “audio”. If an unknown command is received, the device returns “-” and closes the stream. If “audio” is received from the client an acknowledgment is returned (“+”) and the actual audio streaming is started. Incoming audio data from the client is processed in lines 125-137:

    if (my_audio_stream.state == STREAM_STATE_STREAMING) {
		const uint8_t* buf;
		unabto_stream_hint hint;
		size_t readLength = unabto_stream_read(stream, &buf, &hint);
		if (readLength > 0) {
			adpcm_decode(pPlayBuffer, buf, readLength);
			if (!unabto_stream_ack(stream, buf, readLength, &hint)) {
				my_audio_stream.state = STREAM_STATE_CLOSING;
		} else {
			if (hint != UNABTO_STREAM_HINT_OK) {
				my_audio_stream.state = STREAM_STATE_CLOSING;

The data is read from the stream, decoded, and written to the circular play buffer. Processed data has to be acknowledged with unabto_stream_ack(). For the audio encoding ADPCM is used (for implementation details see adpcm_audio.c). It compresses the two 16-bit stereo samples to one single byte. At 16000 samples per second, this results in a transfer bitrate of 16 kbit/s which is no problem for the CC3200, even for encrypted remote connections. If you want to have a more advanced codec like for example Speex, just replace the encoding and decoding functions.

As mentioned before, the uNabto task continuously checks for available recorded audio by calling the stream_audio_write() function. If new encoded audio is available and a stream is established, the data is sent.

void stream_audio_write() {
	if (my_audio_stream.state != STREAM_STATE_STREAMING) {
	size_t encodedLen = adpcm_encode(pRecordBuffer, encodedBuf, sizeof(encodedBuf));
	if (encodedLen == 0) {
	} else {
		UNABTO_ASSERT(encodedLen == sizeof(encodedBuf));

	unabto_stream_hint hint;
	size_t writeLength =
			unabto_stream_write(, encodedBuf, sizeof(encodedBuf), &hint);

	if (writeLength <= 0 && hint != UNABTO_STREAM_HINT_OK) {
		my_audio_stream.state = STREAM_STATE_CLOSING;

	UpdateReadPtr(pRecordBuffer, writeLength * ENCODING_RATIO);

Using the CC3200 Code

You can get the whole CC3200 code including the described platform adapter and the audio streaming device application from the audio branch of our public CC3200 GitHub repository. Simply follow the instructions in the README to set everything up.

The Android Client

The Android audio streaming client is also published on GitHub. It uses our android client SDK available on JCenter (for source code see GitHub repository). It is included in the build.gradle with one single line:

compile ‘’

The main App logic is implemented in Once the unique Device ID is entered in the UI and the OPEN AUDIO STREAM button is pressed, a thread is started to establish the stream connection and send the “audio” command. Then, a recording + sending and a receiving + playing thread are started until the connection breaks or the stream is closed by the user.


To run the App on your Android device, follow the README instructions in the repository. If you enter the Device ID, you should be able to establish a stream connection and hear the microphone (and line-in) input of the opposite device.

Want to learn more about P2P IoT?

Please visit the:
P2P IoT Academy

Deep dive Into our documentation?

Please visit the:
Nabto Platform Overview

Try our demo for Video Surveillance?

Please visit the:
Nabto Edge
Video Cam Demo

Looking for other Great posts?