Implementing the Required Capabilities

After the previous chapters you are mostly ready from the firmware perspective, however there is one more thing that you should add so that the BlueRange platform can properly tell your devices apart and knows what types of sensor values to expect. Therefore, we will now implement a simple capability reporting in the firmware.

There are two different ways of specifying the sensors and actuators that your device is using:

While Sensor and Actuator Settings are intended to be used during the development phase, the device catalog is the go-to feature for production. Using the device catalog will make it possible for the BlueRange platform to automatically select the correct configuration for each of your devices. With configurations, the end user has to manually assign them to each of his devices after enrollment which is inherently error-prone.

There are a number of different capability types which you can check out here. The most important one for our example is the METADATA capability which allows the platform to automatically determine the correct device catalog entry based on the data received by the device at run time. Take a look at the best practice section for some examples and how the different types should be used.

Essentially, our BlueRange Gateway will retrieve all capabilities for each of the enrolled devices. As each module can report capabilities of its own, this can be a process that takes a few minutes. Once it is done, the platform automatically selects the correct entries and your device is ready to be used.

Example Implementation

CapabilityEntry VendorTemplateModule::GetCapability(u32 index, bool firstCall)
    if (index == 0)
        CapabilityEntry retVal;
        CheckedMemset(&retVal, 0, sizeof(retVal));
        retVal.type = CapabilityEntryType::METADATA;
        strcpy(retVal.manufacturer, "Example Vendor");
        strcpy(retVal.modelName   , "Example Device");
        strcpy(retVal.revision   , "1");

        return retVal;
    else if (index == 1)
        //You can implement as many entries as you like,
        //e.g. to report the version of your custom bootloader
        CapabilityEntry retVal;
        CheckedMemset(&retVal, 0, sizeof(retVal));
        retVal.type = CapabilityEntryType::SOFTWARE;
        strcpy(retVal.manufacturer, "Example Vendor");
        strcpy(retVal.modelName, "Bootloader");
        strcpy(retVal.revision   , "1.2.3");

        return retVal;
        return Module::GetCapability(index, firstCall);

What happens is that the gateway will iterate through all capability indices of all modules until the last one with CapabilityEntryType::INVALID is received. In some cases, the firmware will need to acquire the capabilities from a number of sub-devices (components) that are attached e.g. via Modbus, SPI or other technologies. If the required data is not available at the current time, you are free to respond with CapabilityEntryType::NOT_READY which will tell the Gateway that it must retry asking again at a later point.

More on this topic can be found in the capability retrieval chapter.

Testing the Capability Retrieval

To test our implementation, enter the following on the terminal of the flashed device. You can also give any nodeId of another node in your network to retrieve the capabilities over the mesh.

request_capability [nodeId]

//Asks the current node for its capabilities
request_capability this

In response, you should get a number of output jsons similar to the ones below. You might get more output as our sensor implementation will send its counter value each five seconds. Do not disable this, we will need the functionality later.

//This is an entry of type SOFTWARE that tells us the firmware version, it is generated by the Node.cpp
{"nodeId":123,"type":"capability_entry","index":0,"capabilityType":2,"manufacturer":"MWAY DIGITAL GmbH","model":"BlueRange Node","revision":"1.0.1650"}
//This is another entry of type PROPERTY that is used to report the featureset
{"nodeId":123,"type":"capability_entry","index":1,"capabilityType":4,"manufacturer":"MWAY DIGITAL GmbH","model":"Featureset","revision":"prod_template_nrf52"}
//A METADATA entry that tells us this node can report the "BlueRange Node Status"
{"nodeId":123,"type":"capability_entry","index":2,"capabilityType":3,"manufacturer":"MWAY DIGITAL GmbH","model":"BlueRange Node Status","revision":"0"}
//This is what we have just implemented, a METADATA capability with the given Strings
{"nodeId":123,"type":"capability_entry","index":3,"capabilityType":3,"manufacturer":"Example Vendor","model":"Example Device","revision":"1"}
//The final entry telling us that all capabilities have been reported

Best Practice

Having all the different capability types might seem overwhelming at first. We have collected some examples and explanation on how the different types should be used so you should be able to apply this to your product to gain the best experiance for your product and your users. If you simply want to continue with the tutorial, you can skip this chapter and directly continue with the following section.

Let’s assume that we want to integrate a luminaire in the Platform which is called "SuperLum 2000" and your company goes by the name "The Light Company". Your product is a standing luminaire with 2 light heads and consists of a number of internal devices such as a main control unit and a sensor control unit in each of the light heads. Each of your internal devices has a user updatable firmware which is currently at version 1.0.0 for the sensor units and version 1.2.3 for the main control unit. Your product is able to report its current BRIGHTNESS setting for each light head in % and report a TEMPERATURE in °C for each of its light heads.

It is both helpful for support personnel and the end user to know the software and hardware revisions that they are dealing with, so you should report the capabilities SOFTWARE and HARDWARE.

Main Unit Software version:

  • Capability Type: SOFTWARE, Manufacturer: The Light Company, Model: Main Control Unit, Revision: 1.2.3

Main Unit Hardware/PCB revision:

  • Capability Type: HARDWARE, Manufacturer: The Light Company, Model: Main Control Unit, Revision: 1.0.0-final

Sensor Unit Software versions:

  • Capability Type: SOFTWARE, Manufacturer: The Light Company, Model: SuperSense LH0, Revision: 1.2.3

  • Capability Type: SOFTWARE, Manufacturer: The Light Company, Model: SuperSense LH1, Revision: 1.2.3

Sensor Unit Hardware/PCB revisions:

  • Capability Type: HARDWARE, Manufacturer: The Light Company, Model: SuperSense LH0, Revision: 1.1.0-final

  • Capability Type: HARDWARE, Manufacturer: The Light Company, Model: SuperSense LH1, Revision: 1.1.1-fix

Next, you might want to report some additional data as, e.g. the serial number of your luminaire as each of your products is individually manufacturered. You should report this data by using the PROPERTY type.

Luminaire Serial Number:

  • Capability Type: PROPERTY, Manufacturer: The Light Company, Model: Serial Number, Revision: AB1234567

Finally, and most importantly, you need to have a way to identify your product and couple it with either a single or multiple device catalog entries. Let’s assume the easy case that your product supports a fixed set of sensors and actuators. If you can link a revision of your product to a set of sensor values, you only need a single METADATA entry to do the mapping, it would look like this:

Device Catalog Mapping:

  • Capability Type: METADATA, Manufacturer: The Light Company, Model: SuperLum 2000, Revision: 1

This entry will now allow you to use the following folder structure <Device Catalog>\The Light Company\SuperLum 2000\1.json. This json definition will contain the appropriate entries for the BRIGHTNESS and TEMPERATURE sensors, see the Device Catalog Examples chapter.

Here is what you should do, once you update the firmware or hardware of your product so that it supports an additional sensor, e.g. a LIGHTNESS sensor: report a higher revision number 2 for this METADATA entry and place a new .json file under <Device Catalog>\The Light Company\SuperLum 2000\2.json that includes all previous sensors and the additional LIGHTNESS sensor as well.

Afterwards, you can contact us with these changes so that we integrate them into BlueRange.

Now, in a more complex use-case, your product would support two different hardware units in the light heads, the cheap one would only report the temperature and the more expensive one would report the TEMPERATURE and the measured CO2 value in ppm while the main unit would still report the BRIGHTNESS for each light head.

In this case, you will need more METADATA entries as shown below:

Device Catalog Mapping:

  • Capability Type: METADATA, Manufacturer: The Light Company, Model: SuperLum 2000, Revision: 1

  • Capability Type: METADATA, Manufacturer: The Light Company, Model: SuperSense Basic LH0, Revision: 1

  • Capability Type: METADATA, Manufacturer: The Light Company, Model: SuperSense Xtra LH1, Revision: 1

You will then need to have a total of 5 json files to do the mapping for this luminaire:

  • <Device Catalog>\The Light Company\SuperLum 2000\1.json

  • <Device Catalog>\The Light Company\SuperSense Basic LH0\1.json

  • <Device Catalog>\The Light Company\SuperSense Basic LH1\1.json

  • <Device Catalog>\The Light Company\SuperSense Xtra LH0\1.json

  • <Device Catalog>\The Light Company\SuperSense Xtra LH1\1.json

Each of your files must contain the sensors reported by its specific subsystem, which means that the SuperLum 2000\1.json contains the reported BRIGHTNESS for both light head 0 and light head 1. The files SuperSense Basic LH0\1.json and SuperSense Basic LH1\1.json contain the mappings to report the TEMPERATURE for the two individual light heads. Ideally, you would use a different component in each of the files but would have the same register mapping. Finally, the files SuperSense Xtra LH0\1.json and SuperSense Xtra LH1\1.json should contain mappings for both, the TEMPERATURE values and the CO2 sensors.

Some Additional Tips

If possible, use human readable names and do not use _ or CamelCase wording if not necessary as the capabilities are both meant as a technical mapping and to be displayed to the end user. Additionally, refrain from special characters such as e.g. : or / that are not meant to be used in file names.

Do not try to make the mapping overly complex if you are not sure how your product is going to be developed yet. Use a simple mapping with only one device catalog entry which you will be able to extend later with new firmware and hardware versions.

There is no need to convert e.g. your firmware revision to a different notation, use whatever you are currently working with, e.g. 2022-01-02 15:33, 11:11:AA:BC or 1.2.3.

If you have features that can be either active or inactive, e.g. if the user can configure whether your lamp should report sensor values or not or if you have a hardware module that is optional, your firmware can report the METADATA entry if the feature is active and can choose to omit the entry if the feature is disabled.

You can use regex expressions in the device catalog files to match on other capability entries such as HARDWARE or SOFTWARE. You should use this feature only if necessary as it will make the decision process more complex.

Testing our Implementation with the BlueRange Platform

Now, as we have our firmware ready, we are able to actually use our device in a real BlueRange installation. You need to have a BlueRange Gateway and access to our platform to continue. We assume that you are already familiar with the basics on how to enroll devices and navigate around the Portal. If not, take a look at our Quick Start guide to get you started.

Once your BlueRange Gateway and the example device that you have just flashed are enrolled, you can go to the portal and navigate to > Networks > "Your Network" > "Devices" > "All" > "Your Mesh Node" > Device Details.

You should now see the capability that you have implemented: example capabilities

If the capabilities are not visible at first, wait for a few seconds / minutes and reload the page as the gateway will take some time to retrieve all data from the device and upload it to the platform.

Testing the component_act Message through the Portal

For debugging purpose you can also instruct the gateway to execute a custom terminal command. To do this, navigate to > Networks > "Your Network" > "Devices" > "All" > "Your Gateway" > Overview, press Send Terminal Command and enter the following which should switch the LED on.

component_act 0 0xABCD01F0 1 1 2 01

Now, continue with the next chapter that gives you an overview on how to connect to our MQTT Broker to get live data and execute commands using the RWIO interface.