Actions

So far, we have covered devices, schemas, packets, and while each of them is critical to the correct functioning of your fleet, the capability to react to real-world events is lacking. To fix that, we built Actions. Actions make Fostrom programmable. They can transform your fleets from simple telemetry-focused infrastructure to powerful autonomous systems.

Currently, you can have actions trigger on incoming messages, and soon you'll also be able to have them trigger when devices go offline or come back online.

Creating an Action

Before creating an action, you need to have a Message Packet Schema which is either set to Both or Inbound in the Direction Constraint.

To create a new action, click on the New Action button in the Actions tab. You'll need to pick a name, you can add a description, and most importantly, you'll need to pick which Message Packet Schema do you want it to trigger on. The options you see are the packet schemas which are messages, either with no direction constraint or inbound-only.

Inside an Action

Once you create or open an Action, you'll see a text editor and a Deploy button below it. You also have Action Settings, wherein you can change the name and description, and even change the message packet schema it should trigger on.

In the code editor, you can write JavaScript code. We support most non-browser modern JavaScript constructs. The code editor has in-built linting and code completion. You can press Ctrl+Space anywhere to get suggestions. The code editor, while already quite powerful, is a bit rough on the edges and we're actively improving it.

How Actions are executed

We execute code in using a sandboxed Javy-based, but further restricted, WebAssembly environment. There is a limit of 500ms per action run, and if your action takes longer than that, it will be killed. You can see the time your action takes to run in the logs.

Writing Actions

There are only a few special things you need to know when writing your own Actions. Apart from that, its just JavaScript, so feel free to write conditionals, loops, functions, classes, and anything else.

  • The WebAssembly environment is completely sandboxed and does not have access to the internet. When the action is run, certain data is made available to it, which is documented below. You can call functions in the fostrom. namespace to trigger effects such as queueing messages to device mailboxes or triggering webhooks.

  • The environment does not have functions like setTimeout or setInterval. It is not compatible with Node.js and does not support npm modules.

  • The environment has some pre-defined objects available at certain variables, such as msg which contains the message that triggered the action. For quick access, the variables pl or payload can be used to access any field inside the payload. For example: pl.temperature.

  • The environment does have console.debug(), console.log(), console.warn(), and console.error(). When these statements are executed, they're written to the Action Run log. When you test actions in the UI while writing them (coming soon), you'll see the output of console.debug() and console.log(). When actions are trigged by incoming messages, only console.warn() and console.error() calls are stored. We'll make the logging level configurable soon.

  • The functions under the fostrom. namespace are what you'll use to execute any effects. It is important to note that all these functions will show autocompletes in the editor for the various resources, like selecting a device, packet schema, tag, or webhook. You need to choose from this list, and cannot write something else in a string. If you do by mistake, the editor should show you an error. Let's go over the available functions:

    • fostrom.sendMsg(device, packet_schema, {fields})

      Choose the device and packet schema from the autocomplete suggestions. Then provide an object which matches the structure of the packet schema. Note that whenever this function is triggered, the packet will first be processed according to the packet schema, just like incoming datapoints and messages are, before being queued into the device mailbox.

    • fostrom.broadcastMsg(tag, packet_schema, {fields})

      This function is similar to the one above. The only difference is that it will queue the message into the mailbox of each device having the tag. Note that since the mailbox is sequential and devices may be offline or busy processing something else, it is not guaranteed that all devices will see the message at the exact same time. This is a design choice to ensure devices can rely on general ordering to reliably process events sequentially.

    • fostrom.triggerWebhook(webhook, object or string)

      This function will trigger a webhook that you have pre-defined in the Fleet Settings. The webhook needs to be selected from the autocomplete. The second argument should be an object or string depending on the content-type you've selected.

Once you've written the code, click on Deploy Action to save the code. The next time the Action is triggered, it will run your new or updated code.

The work on Actions, as with much else, is ongoing. We're working on making Actions easier to test before deploying and having more complete docs around Actions soon.