mDash device management

mDash is a cloud backend for connected products. Its main purpose to provide remote firmware update, remote device control, and health monitor. It is supposed to be used together with a product-specific cloud service.

mDash is available as a managed service at https://mdash.net, as well as private on-premises installation.

How to enable mDash

Assuming Mongoose is already integrated in your firmware (if not, follow the Integration Guide),

Step 1. Login to https://mdash.net, create a device and copy the device password in the clipboard:

Step 2. Edit mongoose_config.h, enable mDash and set the password:

#define MG_ENABLE_MDASH 1
#define MG_MDASH_KEY "..."           // Paste the copied password here
#define MG_FIRMWARE_VERSION "1.0.0"
#define MG_TLS MG_TLS_BUILTIN

Step 3. Rebuild and reflash

How to perform firmware OTA update

Step 1. Rebuild your firmware .bin file

Step 2. Use Web UI on https://mdash.net to update: click on the "download" button, and select the .bin file:

Alternatively, use can use automation or curl. Get your API key from https://mdash.net/#/keys, then run this command:

curl -su :MDASH_API_KEY -F file=@FIRMWARE.BIN https://mdash.net/api/v2/devices/DEVICE_ID/ota

How to implement device control

The device connects to mDash using secure Websocket link, where it exchanges JSON-RPC frames. There are several built-in JSON-RPC functions implemented by the mDash connector inside Mongoose, but it is possible to add any number of custom JSON-RPC functions. mDash bridges all JSON-RPC requests automatically to HTTP REST.

Let's demonstrate that by implementing a function that lets us read and write any pin remotely. Add that to your main.c:

static void mg_rpc_sys_pin(struct mg_rpc_req *r) {
  int pin = (int) mg_json_get_long(r->frame, "$.params.pin", -1);
  int val = (int) mg_json_get_long(r->frame, "$.params.val", -1);
  if (pin >=0 && val >= 0) {
    hal_gpio_write(pin, val);  // Both pin and val are set: write pin
    mg_rpc_ok(r, "true");
  } else if (pin >= 0) {
    mg_rpc_ok(r, "%d", hal_gpio_read(pin)); // Only pin is set: read pin
  } else {
    mg_rpc_err(r, 500, "%m", MG_ESC("set pin and val"));
  }
}
  // Add after mg_mgr_init():
  mg_rpc_add(&mgr.rpcs, mg_str("Sys.Pin"), mg_rpc_sys_pin, NULL);

Rebuild and reflash. Then you can call your RPC:

curl -su :$MDASH_API_KEY https://mdash.net/api/v2/devices/device1/rpc/Sys.Pin -d '{"pin": 0}'
curl -su :$MDASH_API_KEY https://mdash.net/api/v2/devices/device1/rpc/Sys.Pin -d '{"pin": 0, "val": 0}'

To get a list of all RPCs,

curl -su :$MDASH_API_KEY https://mdash.net/api/v2/devices/device1/rpc/RPC.List

See also: JSON-RPC reference.

How to enable Health Monitor

Currently, Health Monitor is implemented for STM32H7 and STM32H5 series. To enable it, follow the steps below:

Update the linker script file, add this to the no-init RAM region:

  /* Retained health record. Startup code must neither copy nor clear it. */
  .mg_health (NOLOAD) : { KEEP(*(.mg_health .mg_health*)) } > ram_d3

In your mongoose_config.h, enable health monitor:

#define MG_ENABLE_HEALTH 1

That line enables several IRQ handlers - for HardFault, etc. If you're using CubeMX, disable IRQ generation for those in System Core / NVIC.

In your main(), add this line at the very beginning:

int main(void) {
  MG_HEALTH_INIT();  // <-- Add this!

While not necessary, you can add this debug log after the mg_mgr_init():

  MG_INFO(("Crash record: %M", mg_print_crash_record));

Rebuild and reflash. Now, if you're using mdash, you'll get crash backtrace in case if your device crashes. You can either upload the firmware .elf file after the flashing or OTA, or you can download the crash core file and analyse it locally. Change `firmware.elf if required:

arm-none-eabi-gdb -q -nx --batch \
  -ex 'set auto-load off' \
  -ex 'set debuginfod enabled off' \
  -ex 'set print frame-arguments none' \
  -ex 'set backtrace past-main on' \
  -ex 'file firmware.elf' \
  -ex 'core-file crash.core' \
  -ex 'bt'

This is how it looks like on the dashboard when .elf is uploaded:

Note: the .elf files are associated with firmwares by firmware version. That means, once you upload an .elf file, it will work for all devices with the same version. Therefore, make sure to update the MG_FIRMWARE_VERSION when rebuilding your firmware after changes.