🌳 Overview

Overview

The Ivy template provides the key components, we think, almost every data acquisition system (DAS) requires. It is a template that runs as is. You can base any DAS written in Python on Ivy and start with a very powerful and thought-out baseline instead of having to reinvent the wheel. You own the codebase and can strip away everything you don't use and add everything you need for your application.

As an example, Pyra (opens in a new tab) is a DAS we built a few years ago. It does not connect to a backend and is not using Over-the-Air (OTA) updates. However, the rest complies with the Ivy template, and we could have saved a ton of time - and a full rewrite - by using Ivy as a baseline.

Setup, Configuration & the CLI

Ivy/your DAS is set up at ~/Documents/ivy/x.y.z/. The full layout of the file system is described here. It is configured using a JSON configuration file at ~/Documents/ivy/x.y.z/config/config.json. Read more about the configuration object here.

The CLI (~/Documents/ivy/x.y.z/cli.py) is used to start and stop the automation as a background process. Check out the cli.py --help menu and feel free to add any DAS specific commands to your CLI, which will be automatically included in this help menu and the API reference.

Procedures & Failure Handling

Procedures are the place where the logic of the system is executed in an infinite loop: sample from sensory inputs, control actuators, and control electrical components like a PLC or a UPS.

Every procedure will run inside its own thread. You only have to write the procedure as a function that runs infinitely. The Ivy core will start the thread, restart it every time it crashes, and send a teardown signal before stopping it to enable graceful teardowns.

Read more about procedures and how to write your own here.

Sharing State Between Components

The state is the internal mechanism of communicating between procedures and with the Ivy core. I.e., a procedure can periodically write some of its results into the state, and all other procedures can access it and act accordingly. For example, one procedure is catching signals from a UPS about a low battery state and writing that into the state. Other procedures can react to that by skipping energy-intensive tasks.

Read more about how to access the shared state from your code here.

Backend Connectors and Messaging

An Ivy-based network is made up of many (remote) computers running autonomously -e.g., performing measurements, controlling actors, etc. - and a central backend connects these devices. A backend is a central service to collect data (measurements and logs) and configure sensor nodes. Ivy comes with connectors for Tenta (opens in a new tab) and ThingsBoard (opens in a new tab). However, Ivy can work with any backend that is capable of storing tabular data and providing some endpoints to read and write this data.

In Ivy, "Messages" are data structures sent to the backend. These messages can be sent from any part of the codebase - same as logs. All messages will be stored locally right away, and a thread handling the backend communication will send them to the backend. Since the emission is separated from the sending, the procedures producing messages do not have to wait until a message has been sent and can continue their operation after a few milliseconds. This "message sending" is done with the MessagingAgent and is described here.

All messages are stored locally, and if you do not have a backend, you can just leave it unconfigured and simply use that local storage (one file per day) to capture the data.

Read more about Backends and how to set up Tenta (opens in a new tab) and ThingsBoard (opens in a new tab) for Ivy here.

Over-the-Air (OTA) Updates

The config.json file described above can be changed remotely. The backend can publish new configurations to its devices, and Ivy will update itself accordingly.

A change of configuration can either be a "reconfiguration" or a "version change". Ivy runs a suite of pytests on the local machine before switching to a new config/version. In case of a version change, it will download the required source code, install the new dependencies, and remove old dependencies after a successful change.

Read more about OTA updates here.