Tag Archive for: api

The Golioth Zephyr SDK is now 100% easier to use. The new v0.4.0 release was tagged on Wednesday and delivers all of the Golioth features with less coding work needed to use them in your application. Highlights include:

  • Asynchronous function/callback declaration is greatly simplified
    • User-defined data can now be passed to callbacks
  • Synchronous versions of each function were added
  • API is now CoAP agnostic (reply handling happens transparently)
  • User code no longer needs to register an on_message() callback
  • Verified with the latest Zephyr v3.2.0 and NCS v2.1.0

The release brings with it many other improvements that make your applications better, even without knowing about them. For the curious, check out the changelog for full details.

Update your code for the new API (or not)

The new API includes some breaking changes and to deal with this you have two main options:

  1. Update legacy code to use the new API
  2. Lock your legacy code to a previous Golioth version

1. Updating legacy code

The Golioth Docs have been updated for the new API, and reading through the Firmware section will give you a great handle on how everything works. The source of truth continues to be the Golioth Zephyr SDK reference (Doxygen).

Updating to the new API is not difficult. I’ve just finished working on that for a number of our hardware demos, including the magtag-demo repository we use for our Developer Training sessions. The structure of your program will remain largely the same, with Golioth function names and parameters being the most noticeable change.

Consider the following code that uses the new API to perform an asynchronous get operation for LightDB State data:

/* The callback function */
static int counter_handler(struct golioth_req_rsp *rsp)
{
    if (rsp->err) {
        LOG_ERR("Failed to receive counter value: %d", rsp->err);
        return rsp->err;
    }

    LOG_HEXDUMP_INF(rsp->data, rsp->len, "Counter (async)");

    return 0;
}

/* Register the LightDB Get callback from somewhere in your code */
static int my_function(void)
{
    int err;
    err = golioth_lightdb_get_cb(client, "counter",
                                 GOLIOTH_CONTENT_FORMAT_APP_JSON,
                                 counter_handler, NULL);
}

Previously, the application code would have needed to allocate a coap_reply, pass it as a parameter in the get function call, use the on_message callback to process the reply, then unpack the payload in the reply callback before acting on it. All of that busy work is gone now!

With the move to the v0.4.0 API, we don’t need to worry about anything other than:

  • Registering the callback function
  • Working with the data (or an error message) when we hear back from Golioth.

You can see the response struct makes the data itself, the length of the data, and the error message available in a very straightforward way.

A keen eye already noticed the NULL as the final parameter. This is a void * type that lets you pass your user-defined data to the callback. Any value that’s 4-bytes or less can be passed directly, or you can pass a pointer to a struct packed with information. Just be sure to be mindful of the memory allocation lifespan of what you pass.

All of the asynchronous API function calls follow this same pattern for callbacks and requests. The synchronous calls are equally simple to understand. I found the Golioth sample applications to be a great blueprint for updating the API calls in my application code. The changelog also mentions each API-altering commit which you may find useful for additional migration info.

The Golioth Forum is a great place to ask questions and share your tips and tricks when getting to know the new syntax.

2. Locking older projects to an earlier Golioth

While we recommend updating your applications, if you do have the option to continue using an older version of Golioth instead. For that, we recommend using a west manifest to lock your project to a specific version of Golioth.

Manifest files specify the repository URL and tag/hash/branch that should be checked out. That version is used when running west update, which then imports a version of Zephyr and all supporting modules specified in the Golioth SDK manifest to be sure they can build the project in peace and harmony.

By adding a manifest to your project that references the Golioth Zephyr SDK v0.3.1 (the latest stable version before the API change) you can ensure your application will build in the future without the need to change your code. Please see our forum thread on using a west manifest to set up a “standalone” repository for more information.

A friendlier interface improves your Zephyr experience

Version 0.4.0 of the Golioth Zephyr SDK greatly improves the ease-of-use when adding device management features to your IoT applications. Device credentials and a few easy-to-use APIs are all it takes to build in data handling, command and control, and Over-the-Air updates into your device firmware. With Golioth’s Dev Tier your first 50 devices are free so you can start today, and as always, get in touch with us if you have any questions along the way!

Have you tried to use the Golioth Web Console yet? The interface delivers access and control for your entire IoT fleet. This means sending and receiving data in real-time, checking on the state of each device (including current firmware revision), reading logs from the hardware, and more.

Did you know that you can create your own User Interface (UI) like this using any stack you want? That’s because we used REST and WebSocket APIs to build the Golioth Console, and those same APIs are available for you to build any application to fit for our needs.

In this blog, post I will show how simple it is to set up a custom UI project using the Golioth APIs.

To demonstrate, we built a web interface around the image of an Adafruit MagTag, a development board we use for our developer training program. It’s pretty cool to click a button on the the image above and see the device in your hand react. Let’s dive in as I cover the necessary steps to pull it all together.

Golioth Cloud

We begin by using the Golioth Web Console to setup a project and create API Keys. You can also follow the authentication docs where it has a guide for you to do the same but using Golioth Command Line Interface (CLI).

  1. Sign-up/Sign-in on the Golioth Web Console
    • If you created a brand new account, you will see a QuickStart Wizard that guides you through the process of creating a new project and adding a new device
  2. Choose your project using the project selector at the middle-top (I’m calling mine Project 1)
  3. Create an API Key to authenticate on the API’s:
    • Clicking on Create, select API Key and hit Create at the pop-up;
  4. Create a Device
    • Go to Devices at the sidebar and hit Create
    • I’m calling mine magtag, and generating credentials automatically

Firmware

LightDB State - MagTag

LightDB State – MagTag

My physical MagTag is running the latest version of the MagTag Sample using Golioth’s Arduino SDK. With that firmware, my device is set up to use LightDB State to read and set data. That means it will listen for changes on the desired endpoint and update it’s status both physically and on the cloud’s state endpoint to match.

Note: The arduino-sdk repository showcased in this post is deprecated. GoliothLabs has two experimental repositories that may work as replacements:

This state pattern is related to the concept of Digital Twin, which you can read more on our desired state vs. actual state blog post.

Front-end

The front-end was bootstrapped using Vite’s react-ts template. I’m also using Mantine as a component library for this application.

To set up our connection to both the REST and WebSocket APIs, we first need to understand how it should be built. For that, you can easily go to Golioth REST API Docs and Golioth WebSocket API Docs and follow through those steps.

The gist of it is that we need a few pieces of information to authenticate. This includes the Golioth API URL, the project ID we are targeting, and an API key from that project. Since we’re going to target a specific device as well, I also added the Device ID.

With those fields, we’re able to connect and listen to state changes using the WebSocket API. But we also want to display the current state, and be able to update the desired state from here.

Displaying Current State

The data coming from the current state allows us to build a virtual replica of the MagTag on the UI. With some CSS magic we can display its text, leds and light.

{
  "accX": 0.32,
  "accY": 0.11,
  "accZ": -9.89,
  "leds": {
    "0": "#00a2ff",
    "1": "#00ffee",
    "2": "#00ff84",
    "3": "#04ff00"
  },
  "light": 34,
  "text": "Golioth"
}

The theme is also reacting to the light sensor readings from the device. The UI changes to dark mode if the light level is low.

Setting Desired State

To set the desired state, we’re going to send some POST requests using our REST API, using the same API Keys that we input on the form.

LEDs:

Using a modal and a color picker, we can select the colors and press Save.

URL:

https://api.golioth.io/v1/projects/project-1/devices/6283eedd71e8739f42672114/data/desired/leds

Payload:

{
    "3": "#ff0000"
}

Using the same modal and form, we can set all leds states, by clicking on top of the led position.

Text:

Using the same logic, we can also use a modal and a textarea to set the text, with preserved line breaks.

URL:

https://api.golioth.io/v1/projects/project-1/devices/6283eedd71e8739f42672114/data/desired

Payload:

{
    "text": "MagTag"
}

Buttons:

Buttons don’t have an actual state, so here I just added some boxes on top of their positions on the MagTag image.

This way, when we click on them, the application will change the desired buzz state to true.

URL:

https://api.golioth.io/v1/projects/project-

/devices/6283eedd71e8739f42672114/data/desired/buzz

Payload:

true

LightDB State Result:

"desired": {
  "buzz": true,
  "leds": {
    "0": "#ff0000",
    "1": "#00ffee",
    "2": "#00ff84",
    "3": "#1ad57a"
  },
  "text": "MagTag"
}

The device is also listening for changes on the desired state, so when the buzz state changes to true, the device will take action. In this case, the actual MagTag will emit a buzz, and then change the desired buzz state back to 0.

Just a taste of what you can do with a custom UI

The simple steps I’ve shown here are just the beginning of what you can accomplish with your own custom user interface. If you are managing fleets for a customer, you may want to give them a simpler interface that only includes relevant controls and data. Whether it’s a Digital Twin like the MagTag in my example, or more traditional web interface, knowing that Golioth will work for any web-control need you come across is yet another powerful tool to have at your disposal.

See it in action

Every IoT project needs to provision devices that are going to be available in the field. Leveraging open standards, Golioth cuts down on the required time and hassle for IoT development teams.

Provisioning is a critical step in IoT projects when they go to production. Unfortunately, this process remains a mystery for many engineers due to lack of information about the process. At a high level, provisioning is passing configurations and credentials to an IoT device so it can connect securely to the cloud. Once provisioned, the device can send telemetry, receive commands, or be updated (by OTA DFU) when it’s out in the field. How you provision a device depends a lot on the use case. 

(click the image above to see the full diagram)

Example use cases

First, let’s examine a customer-facing product like a smart light bulb. In this scenario, the first step would be for the user to provide WiFi credentials to connect to the user’s home network. On the platform side, the device would obtain a new set of credentials to connect to the backend services. These credentials would be specific to that particular user and device. Later, the user might decide to clean up the device to sell it, so the ability to remove device configurations and deleting a given set of credentials is important. This is a perfect example for using BLE provisioning like shown in the video below.  The user experience is seamless with any existing mobile app used for controlling the bulb and reporting data back from the end device.

Next, we’ll consider factory-level provisioning. An example device like a cellular asset tracker would be pre-provisioned at the factory before being used by your customer. Later the user will only associate that device with their account, but the credentials to talk to the cloud are already set on the device. This can be done as part of the manufacturing process, probing the device via Serial/UART to get the device hardware ID, provisioning it to the cloud, and sending credentials back to the device via the same transport. We can even have different firmware that will only provision in the factory. The device accepts the initial device configuration and saves the credentials to flash. Subsequent firmware that doesn’t have that initial feature enabled, making sure external parties can’t change or reverse engineer the initial configuration.

There are myriad ways that provisioning can be done. Each instance will depend on the factory environment, the capabilities of the user, and on the end application. The video below is a setup similar to the first example explained above, using a Bluetooth application to read and then program the end device, all while working with the Golioth cloud.

Our demo application

As you can see in the video, we developed an end-to-end sample that shows a practical scenario of provisioning IoT devices with a native mobile app, talking with an IoT device over Bluetooth, and provisioning device/credentials in Golioth Cloud. We leverage different tools for doing so:

  • MCUmgr as the device management subsystem and protocol.
  • Zephyr as the real-time operating system, that implements MCUmgr.
  • Open-source mobile SDK to integrate MCUmgr on an app
  • Golioth’s API and the Device/Credentials Management capabilities. 

The MCUmgr community developed multiple types of transports to interact with devices, a benefit of MCUmgr being an open standard and having a vibrant community. One option is to communicate with the device over serial UART using the `mcumgr` cli or even integrate that into your own set of provisioning tools. Another option is to use a mobile SDK that implements MCUmgr protocols over BLE to talk with devices.

We took the Bluetooth approach and forked Nordic’s MCmgr Example application, adding communication with Golioth APIs to manage devices. Once we discover the name of the device, we assign credentials via the REST API and securely send them over Bluetooth to the end device. The device is running one of Golioth’s samples that accepts dynamic configuration for WiFi and DTLS Pre Shared Keys to talk securely with our cloud. The device uses a different Golioth service called LightDB. Using this configuration engine, we can publish the on/off state of the light bulb using LightDB,show that data on a UI, and even send commands to change the state on the device. 

Source code for the mobile app:

More details on how to use our REST API and how to generate API Keys can be checked on our docs website.

References