# Create a calculated function
Author: Marcus Rejås, IoT Open User and IoT Open Employee
# Background
This story is originating from a question from a customer but I think it can be applied to many different use-cases so I wrote this story.
The question from the user was regarding measure of water level in a cistern of some kind. This is done by measure the distance from the sensor to the water surface (x in the figure below). But what they want do see is is the distance between the bottom and the surface i.e. the water depth. In this case the distance between the sensor and the bottom is 1200mm and from that we can calculate the water depth.
The value we want is then 1200 - x = Depth where x is the value from the sensor.
# The solution
Instead of manipulating the measurement we get from the sensor we use it to create another function representing the depth. This is good because they are both valid measurements. By doing this we can then use both the values in IoT Open and other integrations.
Assume we already have the function "Distance from sensor" we create another generic function called "Water depth" and then make a module that whenever "Distance from sensor" is changed the "Water depth" is also changed. In this case we use Node-RED for this but it may be implemented in several different ways.
# Prerequisites
You will need an IoT Open installation and a function giving the start value (the sensor in this example). If you just want to elaborate on this you can use any function.
You will also need an API key for your user in IoT Open to be able to access the data from the functions.
You will also need a Node-RED instance with the Lynx Nodes installed. See this guide for more info on how to set this up.
# Steps
These are the steps we need to accomplish.
- Create the function that should carry the calculated value in IoT Open
- Build the calculation
- Test that it works
# Create the function that should carry the calculated value
First lets create the function that should hold the calculated value. This is done in the IoT Open Web Interface (or via the API).
I created the function and called it "Water depth". Go to the installation and click on Functions to list all the functions for the installation. At the bottom there are a drop down where you can add a generic function.
There are not much you need to fill in, but the fields below are mandatory. The read_topic needs to start with obj/<something>/ if this is unfamiliar to you see the documentation.
# Build the calculation
The calculation is simple in this case. Whatever value comes in from the sensor should be subtracted from 1200 to get the water depth in millimeters. This is easily done with Node-RED but could also be done by other means.
Log in to Node-RED and create a new Flow. Add Lynx-In node where we select the function from the sensor.
To be able to see the data that comes in connect the new node to a debug node. Now every time a measurement from the sensor comes in it should be visible in the debug pane. You may leave the debug node during the development process.
Then add a Lynx out node and select the function you created earlier. The nodes should be connected later on.
Finally add a function node between the two nodes.
In the function node we need to add the code for the calculation witch in this case is simple.
msg.payload.value = 1200 - msg.payload.value;
return msg;
The second line is already there, you just have to add the first one.
The flow now looks like this (with the function open)
# Test that it works
Now we have to wait for data to come from the sensor (or create fake data). We should now see in Lynx that data comes in on both functions at approximately the same time.
Below we can see the values in Lynx Web Interface. Of course you can use it in all you Lynx tools like Grafana and others.