Scaling an IoT deployment? Join our webinar on May 28th where we dive into real-world scaling pain points and how to overcome them.

Blues Developers
What’s New
Resources
Blog
Technical articles for developers
Newsletter
The monthly Blues developer newsletter
Terminal
Connect to a Notecard in your browser
Developer Certification
Get certified on wireless connectivity with Blues
Webinars
Listing of Blues technical webinars
Blues.comNotehub.io
Shop
Docs
Button IconHelp
Notehub StatusVisit our Forum
Button IconSign In
Sign In
Sign In
What’s New
Resources
Blog
Technical articles for developers
Newsletter
The monthly Blues developer newsletter
Terminal
Connect to a Notecard in your browser
Developer Certification
Get certified on wireless connectivity with Blues
Webinars
Listing of Blues technical webinars
Blues.comNotehub.io
Shop
Docs
homechevron_rightBlogchevron_rightSending and Receiving Binary Files with the Notecard and Notehub

Sending and Receiving Binary Files with the Notecard and Notehub

Sending and Receiving Binary Files with the Notecard and Notehub banner

November 28, 2023

Learn how to use the card.binary APIs to send and receive files from/to a Micro SD card using the Blues Notecard and Notehub.

  • Arduino
  • Binary Files
  • Firmware
Rob Lauer
Rob LauerSenior Director of Developer Relations
email

The Notecard was originally designed as a low-bandwidth and low-power device that effortlessly syncs user-defined JSON payloads (e.g. key-value pairs of strings, booleans, and integers) with any cloud endpoint. However, one of the most-repeated requests we heard from customers is the ability to also sync larger payloads of binary data (most often in the form of images).

With the release of the Notecard developer firmware release v5.3.1, this is now possible using the new card.binary APIs. Even better, our firmware libraries for Arduino/C and Python abstract away the complexity of the card.binary requests for you.

In this article, I'm going to show an example in Arduino/C of how to:

  1. Request a JPEG image from a cloud endpoint.
  2. Write that JPEG image to a Micro SD card.
  3. Send that same JPEG image back to a different cloud endpoint.

Hardware Setup

For this example, I'm using the following hardware:

  • Blues Swan (STM32L4-based host MCU)
  • STLINK Programmer/Debugger (optional, but makes working with STM32-based MCUs more pleasant)
  • Blues Notecard Cellular (any Notecard will do!)
  • Blues Notecarrier A (a development board for interfacing with the Notecard)
  • Adafruit's Micro SD breakout board
  • 2 x LiPo batteries

Wiring the Micro SD Breakout to the Swan

First, you'll want to wire up the Swan to the Micro SD breakout. The following table outlines the wiring needed to connect the two:

SD BreakoutBlues Swan
GNDGND
3v3V3
CLKCK
DOMI
DIMO
CSA3

Attaching the Notecarrier to the Swan

Next, attach the Notecarrier A to the Swan via a Qwiic cable. Note that the Swan and Notecarrier A also need to be powered separately either over Micro USB or an attached LiPo battery, as Qwiic doesn't deliver enough power to boot the Notecard.

Your hardware should look something like the following (with or without the STLINK debugger of course):

wiring sd breakout to swan and notecarrier

Format the Micro SD Card

If you haven't already, be sure the Micro SD card you're using is already formatted as either FAT16 (if < 2GB) or FAT32. If not, you can use a USB SD card reader with your PC to format it using the SD Association's Memory Card Formatter (available on macOS/Win and Linux ).

Now it's time to write the sketch!

note

Looking for a shortcut? Check out this gist to see the completed sketch.

Setup the Notecard and SD Card Breakout

Include the necessary libraries in your project, including note-arduino for the Notecard and the Arduino SD Library for the Micro SD breakout board. Also, add the variables needed to interface with the components:

#include <Arduino.h>
#include <Wire.h>
#include <Notecard.h>
#include <SD.h>

Notecard notecard;
File myImageFile;
Sd2Card card;
SdVolume volume;
SdFile root;
const int chipSelect = A3;
HardwareSerial stlinkSerial(PIN_VCP_RX, PIN_VCP_TX);
#define usbSerial Serial

int ledPin = LED_BUILTIN; // references onboard LED on Swan

Initialize the Notecard and Micro SD Breakout

Most everything else occurs in the setup() method.

Set the pinMode of the Swan's onboard LED to OUTPUT so we can blink it later. Also, if you're using the STLINK, be sure to initialize it so you can see output in the serial monitor.

pinMode(ledPin, OUTPUT);

Wire.begin();

// if using STLINK debugger
stlinkSerial.begin(115200);
const size_t usb_timeout_ms = 5000;
for (const size_t start_ms = millis(); !stlinkSerial && (millis() - start_ms) < usb_timeout_ms;)
  ;
  
notecard.setDebugOutputStream(stlinkSerial);

Next, initialize the Notecard, link your Notecard to your project in Notehub via the product key, and reset the Notecard's binary storage area to make sure we have the space required to save an image.

If you haven't set up a Notehub account yet , you should, because it's free to use (up to 5,000 events routed per month!) and only takes an email address.

notecard.begin();

J *req = notecard.newRequest("hub.set");
JAddStringToObject(req, "product", "com.your.project:uid");
JAddStringToObject(req, "mode", "continuous");
JAddBoolToObject(req, "sync", true);
notecard.sendRequestWithRetry(req, 5);

// wait until we are connected to notehub
// this is REQUIRED when sending binary data!
bool connected = false;
while (!connected)
{
  req = notecard.newRequest("hub.status");
  J *rsp = notecard.requestAndResponse(req);
  connected = JGetBool(rsp, "connected");
  delay(2000);
}

// Reset the Notecard's binary storage area, so we can start fresh
NoteBinaryStoreReset();

Next, initialize the connected Micro SD card:

// init the SD card for usage
stlinkSerial.println("Initializing SD card...");

if (!card.init(SPI_HALF_SPEED, chipSelect))
{
  stlinkSerial.println("SD card initialization failed!");
  while (1);
}

// try to open the 'volume'/'partition' - it should be FAT16 or FAT32
if (!volume.init(card))
{
  stlinkSerial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
  while (1);
}

That's it for our initialization tasks. Next up, it's time to request an image file!

Request an Image from the Cloud

For security reasons, the Notecard cannot connect directly to any arbitrary cloud endpoint. It doesn't have a public IP address, nor would you want it to have one. This is where Notehub comes into play, as the Notecard and Notehub work together to form a secure "off the public Internet" link.

To request a binary file from a cloud end point, we'll have to set up a Notehub Route.

note

Routes allow you to send data from Notehub to a public cloud like AWS, Azure, or Google Cloud, a messaging platform like MQTT, or a custom HTTP/HTTPS endpoint. Routes are defined in a Notehub for a single project, and can target any number of Notecard fleets and devices.

Let's say you have a cloud endpoint that will return binary data (i.e. an image file). Make sure you have the URL of the endpoint available.

In Notehub, navigate to the Routes menu option, and create a new Proxy for Notecard Web Requests route:

create proxy route

Supply an arbitrary Route Name and the URL that Notehub should use to fetch the image with a GET. Also, you'll need to add an arbitrary Alias string, which is how you'll reference this Route in the sketch below.

set up proxy route

That's it!

Back in your sketch, you'll use the web.get API to call the newly-created Notehub Route (called GetImage) and store whatever binary data is returned in flash on the Notecard:

J *req = NoteNewRequest("web.get"))
JAddStringToObject(req, "route", "GetImage");
JAddBoolToObject(req, "binary", true);

if (!NoteRequest(req))
{
  notecard.logDebug("Error receiving image\n");
}

uint32_t data_len = 0;
NoteBinaryStoreDecodedLength(&data_len);

uint32_t rx_buffer_len = NoteBinaryCodecMaxEncodedLength(data_len);
uint8_t *rx_buffer = (uint8_t *)malloc(rx_buffer_len);

// Receive the data
NoteBinaryStoreReceive(reinterpret_cast<uint8_t *>(rx_buffer), rx_buffer_len, 0, data_len);
notecard.logDebugf("\n[INFO] Received %d bytes.\n", data_len);

Save the Image to the Micro SD Card

Next, you'll want to write the saved binary buffer from the Notecard to the Micro SD card, using methods provided by the Arduino library:

// save the buffer to the specified file name on the SD card
SD.begin(chipSelect);
SD.remove("logo.jpg"); // remove the file if it already exists
myImageFile = SD.open("logo.jpg", FILE_WRITE);

if (myImageFile)
{
  myImageFile.write(rx_buffer, data_len);
  myImageFile.close();
  stlinkSerial.println("Completed writing the file!\n");
}

You can now pull the SD card out of the breakout board and pop it into your PC to see if the file was saved correctly (in my case I downloaded the Blues logo of course).

blues logo

Yes you'll just have to take my word that it worked!

Send the Image Back to a Cloud Endpoint

So far you've downloaded a file and saved it to SD, but what about uploading it back to another cloud endpoint?

Welcome to the magic of Notehub Routes (yes, they work both ways)!

Back in Notehub, again navigate to the Routes menu option, and create a new General HTTP/HTTPS Request/Response route (this is different than the Proxy for Notecard Web Requests route type, as this time we will be generating a payload locally using Notes to send data from the Notecard to Notehub).

create https route

Provide an arbitrary Route Name and the remote URL that Notehub will use to POST the binary data. In my case, I used the venerable webhook.site for an easy way to inspect outbound data to the cloud.

configure https route

Continue to the Filters section and be sure that you are only routing data from the Notecard that appears in the binary.qo Notefile (this is the name of the Notefile that will contain the binary payload).

configure https route

All set? Back to your sketch!

const uint32_t notecard_binary_area_offset = 0;
NoteBinaryStoreTransmit(reinterpret_cast<uint8_t *>(rx_buffer), data_len, sizeof(rx_buffer), notecard_binary_area_offset);
notecard.logDebugf("\n[INFO] Transmitted %d bytes.\n", data_len);

// Send the binary data to Notehub
if (J *req = notecard.newRequest("note.add"))
{
  JAddStringToObject(req, "file", "binary.qo");
  JAddBoolToObject(req, "binary", true);
  JAddBoolToObject(req, "live", true);
  notecard.sendRequest(req);
}

// Free the receive buffer
free(rx_buffer);

stlinkSerial.println("Completed sending the file!\n");

Believe it or not, that's all that is required. In this code block, you are using the saved binary buffer that's already stored in flash on the Notecard (the image file just downloaded previously) and sending it to Notehub using the note.add API. Note that you're also supplying the binary:true and live:true arguments of note.add in order to pass the binary data from the Notecard to Notehub!

Viewing the Binary Payload in the Cloud

Depending on how you set up the Notehub Route that POSTs data, you should be able to see the binary data delivered. As mentioned earlier, I used webhook.site which lets me inspect delivered payloads. Here is a snippet of the binary file I delivered:

webhook post results

Wrapping Up with a Blink and a Loop

Since I like to get some visual indication that my sketch has run to completion, in the loop() method, I simply flash the Swan's onboard LED on and off:

void loop()
{
  // Finally, blink the Swan's LED when done!
  digitalWrite(ledPin, HIGH);
  delay(1000);
  digitalWrite(ledPin, LOW);
  delay(1000);
}

For a quick view of the full Arduino sketch, consult this gist .

Next Steps

What I've shown here is a relatively simple way of downloading and uploading binary data with the Notecard. More likely you may be dealing with larger binary files that have to be processed in "chunks" that the Notecard can handle. Be sure to consult our additional example Arduino sketch that shows how to accomplish this more advanced scenario.

If you haven't already, grab your own Blues Starter Kit and see how easy it really can be to sync data from a physical device to the cloud (over Cellular, Wi-Fi, or LoRa!).

Happy Hacking! 💙

In This Article

  • Hardware Setup
    • Wiring the Micro SD Breakout to the Swan
    • Attaching the Notecarrier to the Swan
  • Format the Micro SD Card
  • Setup the Notecard and SD Card Breakout
  • Initialize the Notecard and Micro SD Breakout
  • Request an Image from the Cloud
  • Save the Image to the Micro SD Card
  • Send the Image Back to a Cloud Endpoint
  • Viewing the Binary Payload in the Cloud
  • Wrapping Up with a Blink and a Loop
  • Next Steps

Blues Developer News

The latest IoT news for developers, delivered right to your inbox.

Comments

Join the conversation for this article on our Community Forum

Blues Developer Newsletter

The latest IoT news for developers, delivered right to your inbox.

© 2025 Blues Inc.
© 2025 Blues Inc.
TermsPrivacy
Notecard Disconnected
Having trouble connecting?

Try changing your USB cable as some cables do not support transferring data. If that does not solve your problem, contact us at support@blues.com and we will get you set up with another tool to communicate with the Notecard.

Advanced Usage

The help command gives more info.

Connect a Notecard
Use USB to connect and start issuing requests from the browser.
Try Notecard Simulator
Experiment with Notecard's latest firmware on a Simulator assigned to your free Notehub account.

Don't have an account? Sign up