====Simple Example Funnels====
===Difference Calc ===
Let's imagine we have a simple analytic - we'd like to record a //differential// temperature (the difference between two temperatures) from ARDI to a MySQL database.
In this case, we can identify the source (**ARDI**) and the sink (**MySQL**).
From our [[filter_list|filters]], we need to find a suitable filter to calculate the difference. It just so happens that we have a filter named [[filter_difference|Difference]] that does the job for us. It takes all of the input values and returns the difference between the maximum and the minimum value of that row.
So we create the following funnel using XML...
('Machine 1','Machine 2') ASSET 'Temperature' PROPERTY VALUESMachineTempDiff
recordings
name,stamp,value'difftemp',NOW()
**Channels** defines the measurements we are interested in loading from the //source//.
The [[filter_Difference|Difference]] filter returns the difference between the minimum and maximum value of each row.
The [[filter_Change|Change]] filter stops the funnel from completing unless there is a change to the output data. This prevents the analytic system from storing/sending redundant duplicate data.
The [[filter_SQL|SQL]] filter creates a SQL insert string based on the incoming data frame that can be sent to SQL-compliant sinks.
===Rolling Average ===
Now we'd like to calculate a rolling average of our temperature from ARDI. In this case, we'd like to send the information to Microsoft SQL Server and REDIS.
In this case, we can identify the source (**ARDI**) and the sinks (**MSSQL** and **Redis**).
In this case, [[filter_mean|Mean]] is appropriate. It takes all of the input values and returns the mean of each column.
But we have an issue - how do we make this the mean of //30 seconds// of data?
This is where [[buffering|buffering]] comes in.
We can request that Analytics keeps a certain amount of data in a buffer to be processed. In this situation, we can specify a fixed value of 30s.
So we create the following funnel using XML...
('Machine 1') ASSET 'Pressure' PROPERTY VALUES30
**Buffer** sets the funnel buffer to a fixed 30s of data, with no de-duplication.
The [[filter_Mean|Mean]] filter calculates the average of all of the rows, resulting in a single row containing the average of every column.
The [[filter_Throttle|Throttle]] filter ensures that the funnel only executes a maximum of once every 30 seconds, reducing the amount of redundant data storage.
===Converting Discrete Values to Time Ranges===
A common question is "how long was the machine running?", or "how long was it in this state?"
Using analytics, you can convert your discrete values to time frames, which changes this...
^Time^Value^
|01:00|0|
|01:01|0|
|01:02|0|
|01:03|1|
|01:04|1|
|01:05|0|
To this...
^Time^Value^Start^End^
|01:00|0|01:00|01:03|
|01:03|0|01:03|01:05|
('Machine 1') ASSET 'Running' PROPERTY VALUES
frames
name,value,fromtime,totime'motorrun'
**Buffer** sets the funnel buffer to be dynamic (infinite length & purged on output), with deduplication.
The [[filter_DiscreteFrame|DiscreteFrame]] filter stops the funnel from outputting until the value changes, and radically alters the content of the data frame to include 'start' and 'end' times.
As the DiscreteFrame filter only produces output when the state of the input changes, there's no need to put any filters in to control output rate (such as **Throttle** or **Change**_.