Introducing Eclipse Mita - A Language for Embedded IoT

The Internet of Things (IoT) is all about connectivity and scalability. A lot of great technology exists on the cloud side of the IoT which enables fast prototyping, yet scales as the amount of data and number of devices increases. However, the things (embedded, connected sensor devices such as the Bosch Cross Domain Development Kit - XDK) in IoT remain elusive to a lot of developers.

There are many things to learn and consider when building IoT solutions. For example, embedded IoT devices require a very different technology stack compared to the cloud. Bare-metal devices powered by ARM Cortex-M class microcontrollers are most commonly programmed in C which is far less convenient, productive and easy to learn when compared to the programming languages we use in the cloud. Finally, different programming style and often complex APIs present a barrier to developers wanting to build embedded IoT solutions.

Existing technologies that aim at making embedded devices easier to program, e.g. Arduino, work well for prototyping. However, when trying to scale these prototypes towards real-world deployment, let alone to production levels, such platforms fall short. The level of control over timing, memory, and behavior that such existing technologies provide, often do not fit the requirements of commercial IoT deployments.

Eclipse Mita is a new project in the Eclipse IoT family which aims to remove the entry barrier to embedded IoT development and to close the gap between cloud developer experience and the embedded IoT one. Mita is a new programming language designed to feel like modern programming languages in the vein of TypeScript, Kotlin, and Go.

Eclipse Mita:

  • Combines imperative programming with model-driven configuration.
  • Scales from prototypes to commercial IoT deployments by transpiling to C code.

This way developers can inspect, learn, and build on Mita results, thus enabling trust, control and efficiency. Because it was built using Eclipse Xtext, Mita offers a great developer experience sporting auto-complete, syntax highlighting, and a lot of static validation.

With Mita we target resource-constraint devices, often powered by ARM Cortex-M class microcontrollers, limited in RAM, program size and energy available. To leverage the debugging tools, efficient compilers and existing platforms built for such devices, we transpile Mita to C code. Device vendors ship drivers and other libraries which we leverage in the generated C code. Mita is event-based, e.g. events triggered by sensors, connectivity, or time. This development style fits well to the IoT where devices spend most of their time in power-saving modes, wake up due to some event, process data, send it out, and go back to sleep.

Model driven configuration

At the core of Mita are platforms which describe the devices Mita generated C code can run on. Each platform (e.g. the XDK110 platform for the Bosch XDK) provides two key concerns:

  1. How code looks like: there are several implementation details which differ across platforms, e.g. how the system starts up, how timers are used, how events are handled or how the Makefile should look like.
  2. System resources: All devices sport different sets of connectivity, sensors, general-purpose IO and hardware interconnectivity (e.g. I2C or SPI). In addition, the SDKs and libraries that ship with the device provide additional resources, such as application level protocols. Platforms describe all those resources, their configuration items, runtime readable state (called modalities, thing sensor data) and communication channels with the outside world, called signals.

Example

Let's have a look at an example and use the Bosch XDK to build a shock detector connected using MQTT over WLAN:

// Mita has packages which are the main unit of isolation
package main;
 
// Every Mita program must import a platform, here we use the XDK
import platforms.xdk110;
 
// System resources are configured using the setup keyword.
// Here, we configure the WLAN connectivity of the XDK.
setup devnet : WLAN {
    ssid = "MyWifiName";
    psk = "supersecretkey";
}
 
// Software resources are resources nonetheless and thus are set up
// using the setup keyword. Notice how we refer to the devnet WLAN setup
// as means of transport, and instantiate a signal to the /events topic.
setup backend : MQTT {
    transport = devnet;
    url = "mqtt://iot.eclipse.org:1883";
    clientId = "shockDetector42";
   
    var events = topic(name="/events");
}
 
// Functions use the fn or function keyword. If the return type were omitted
// the Mita compiler would infer it automatically. Also, notice the type
// parameter of the array.
fn mean(x : array<uint32>) : uint32 {
    ...
}
 
// Variables can be immutable (let) or mutable (var).
// For arrayPosition we do not have to explicitely give a type as our
// type inference infers it from the initialization.
let acceleration = new array<uint32>(size=10);
var arrayPosition = 0;
 
// The every keyword handles events. Here we use time as an event source and
// run at a regular interval.
every 10 milliseconds {
    // Sensor data (and other modalities) are available due to the platform import above.
    // One can use some resources even if they were not configured beforehand.
    acceleration[arrayPosition] = accelerometer.magnitude.read();
    arrayPosition = (arrayPosition + 1) % acceleration.length();
 
    // The mean() function can be called using the familiar OO-style notation.
    // The expression on the left side of the dot becomes the first argument
    // of the function call.
    if(acceleration.mean() > 5000) {
        // Writing to the signal instance we've created in the signal block
        // above sends out the MQTT message (backend is an MQTT resource
        // after all). Using backticks we can use string interpolation.
        // Here we construct a JSON string inline to the function call.
        backend.events.write(`{ "type": "shock", "mag": ${acceleration.mean()} }`);
    }
}
 
// Events are described and offered by the platforms.
// This pressed event exists because the xdk110 platform imported
// above declares it.
every button_one.pressed {
    for(var i = 0; i < acceleration.length(); i++) {
        acceleration[i] = 0;
    }
    arrayPosition = 0;
}

Conclusion

Eclipse Mita is a new programming language for the embedded IoT. It aims to close the gap between cloud and embedded development, bringing both communities closer together. We support high-level features by combining a model-driven with an imperative language approach, transpiling to C. This affords control over our devices and scales from prototype to production.

The next items on the roadmap after the initial contribution are supporting more platforms, improving the type system and extending the event handling.

If you have any questions, or would like to help out building Mita, please get in touch on the mailing list.

About the Author