Skip to main content
Skip table of contents

Calculated Inputs

Note: These features can only be accessed by Client Admin users. Your Wildeye devices may be managed by a third party as a service.

Accessing

Calculated Inputs can be added to a Site from the "Other" section of the Inputs settings page.

Overview

A Calculated Input is a function of one or more Inputs from the same or different Sites.

Calculated Inputs are an advanced feature that require some level of programming knowledge to create.

Calculated Inputs are written in VB.NET. After creation they are complied and will be triggered to run automatically when new data from all referenced source Inputs is uploaded into the cloud.

You can still benefit form the power of Calculated Inputs without writing code. Calculated Inputs are automatically created and compiled when required with the Add Sensor templating feature.

You can jump to some example functions below to get a better understanding.

Input Class

image-20240411-013044.png

TriggerType Enum

image-20240411-013101.png

Basic Usage

Reference an Input on the current site:

Inputs.Input Name

e.g. Inputs.Rain Fall

LogicalInputs.Input Logical Name

e.g. LogicalInputs.C1


Reference an Input on another site:

Outposts.Outpost Name.Inputs.Input Name 

e.g. Outposts.Station A.Inputs.Temperature

Loggers.HumanId.Inputs.InputName

e.g. Loggers.OP12345.Inputs.Flow


Reference Previous Value of the Calculated Input Itself:

PreviousValue

e.g. Return PreviousValue + Inputs.Input A.Value

Similar to Input.PreviousValue property, the PreviousValue property references the previous value of the calculated input itself.

The Input.PreviousValue property from all source inputs and the PreviousValue property will always have the same datetime.

Please note that the Input.PreviousValue property may not be the actual previous value of the source input. It is the last known value that generated a valid data for the calculated input. 

Log time of PreviousValue: This is not directly available; Get the PreviousLogTime of one of the inputs to the CI, e.g. Inputs.Flow.PreviousLogTime

 


Reference Site Custom Field Value (return type: string):

CustomFields.Field Name

e.g. CustomFields.Field 1

Outposts.Site Name.CustomFields.Field Name

e.g. Outpost.Station A.CustomFields.Field 1

 


Reference Input Custom Field Value (return type: string):

Inputs.Input Name.CustomFields.Field Name

e.g. Inputs.Flow.CustomFields.Field 1

Outposts.Site Name.Inputs.Input Name.CustomFields.Field Name

e.g. Outposts.Station A.Inputs.Flow.Field 1

 


Set Default Value Used in Calculation When Input Has No Data

##Inputs.InputName.NoDataDefault (line must start with ##)

e.g. ##Inputs.Flow.NoDataDefault = 0

 


Set Calculation to Always Trigger

##Inputs.InputName.Trigger (line must start with ##)

e.g. ##Inputs.Flow.Trigger = TriggerType.Always


Data Aggregation

Input.PreviousValue and Input.PreviousLogTime refer to the previous data point that is used in the calculation. They do not necessarily represent the actual previous data point of the input.

For example, when one of the source inputs used in the calculation has a single data gap, that data point is skipped for all source inputs used in the calculation. This means Input.PreviousValue for the subsequent calculation will reference the value before the gap for all source inputs. Not the actual previous value.

Another example is when the source inputs used in the calculation have different logging frequencies. The lowest frequency will be used in the calculation and inputs with higher logging frequency will have their data aggregated to the lowest frequency. Aggregation will be as follows:

Counter inputs: Sum All other inputs: Average Aggregation is done of data point from the current calculated point to the last data point before the next calculated point.

The Input.PreviousLogTime for all source inputs will always have the same value.

Example:

Input A and B are referenced by a CI; Input A is logging at a higher frequency than input B; The CI doing a calculation at the frequency of the referenced input with the lowest frequency, i.e. input B in this case; The values of the higher frequency input are aggregated to give a single value to use in the CI;

The reason it is done this way is to align the input data in time when a CI is referencing multiple inputs. This is also applied when a CI references only one input, but is not necessary.

image-20240411-030801.png

Advanced Settings

The advanced settings can be access by clicking on the advanced settings link on the top right of the screen.

image-20240411-031139.png

Replace source input data gaps with value

The "Replace source input data gaps with value" feature will replace any gaps in the source data with a specified value. This is useful when multiple source inputs are used in the script and the user does not want data gap caused by gaps in one of the source inputs.

Please note that the fill gap feature does not prevent calculated input from stop calculating due to no data in one of the source input. A gap must have data on both sides.

Group source input data with function

The "Group source input data with function" feature applies an aggregated function such as daily total on all source input data before passing them into the user script.

Calculate data after

The "Calculate data after" feature is useful for removing unwanted test data as well as speed up the initial calculation process.

After a CI is created or triggered to recalculate it will process historical input data as follows:

CI's will

  • never start calculating earlier than the 1st available data points of the inputs referenced by the CI,

  • not process data older than 3 years (to optimise performance), except

  • if an earlier start date is specified in the CI's advanced setting "Calculate data after". If a start date is specified the CI will start calculating from that date.

Start date example:

image-20240411-031216.png


Examples

Rates

Create Flow Rate (unit / s)

CODE
If Inputs.Flow.PreviousValue.HasValue Then
  Return (Inputs.Flow.Value - Inputs.Flow.PreviousValue) / Inputs.Flow.LogTime.Subtract(Inputs.Flow.PreviousLogTime).TotalSeconds
End If
Return 0

Create Flow Rate (unit / min.)

CODE
If Inputs.Flow.PreviousValue.HasValue Then
  Return (Inputs.Flow.Value - Inputs.Flow.PreviousValue) / Inputs.Flow.LogTime.Subtract(Inputs.Flow.PreviousLogTime).TotalMinutes
End If
Return 0

Convert an amount per log interval to a rate, e.g. convert a pulse input to litre/min or mph

CODE
'Convert an amount per log interval to a rate, e.g. convert a pulse input to litre/min or mph
Dim PulseIn As Input = Inputs.WindSensor 'or Inputs.FlowSensor, etc.

If PulseIn.PreviousValue.HasValue Then
  Return PulseIn.Value / PulseIn.LogTime.Subtract(PulseIn.PreviousLogTime).TotalHours ' or TotalSeconds or TotalMinutes
End If
Return 0

Filters

Return DateTime Filtered Data

CODE
'return data between 9 AM to 9 PM only
If Inputs.C1.LogTime.Hour >= 9 AndAlso Inputs.C1.LogTime.Hour < 21 Then
  Return Inputs.C1.Value
End If
Return 0

'return data for year 2017 only
If Inputs.C1.LogTime >= New System.DateTime(2017, 1, 1) AndAlso Inputs.C1.LogTime < New System.DateTime(2018, 1, 1) Then
  Return Inputs.C1.Value
End If
Return 0

'return data for week days only
If(Not ((Inputs.C1.LogTime.DayOfWeek <> System.DayOfWeek.Saturday) AndAlso (Inputs.C1.LogTime.DayOfWeek <> System.DayOfWeek.Sunday))) Then
  Return Inputs.C1.Value
End If
Return 0

Remove steps and spikes from a series

CODE
'Remove spikes and step jumps that are bigger than a specified fraction of the input.
'For detail see https://outpost.atlassian.net/wiki/x/5YB-/

Dim RAW As Input = Inputs.Air Pressure

'Linear scaling of RAW input
Dim Scale As Double = 10

'Fraction of RAW input at which step would be removed
Dim StepSizeCutoff As Double = 0.9

Dim RAW_v As Double = RAW.Value * Scale

If PreviousValue.HasValue AndAlso RAW.Previousvalue.HasValue Then
  Dim RAW_pv As Double = RAW.Previousvalue * Scale

  'Extract previous adjusted RAW value from CI result
  Dim pav As Double = PreviousValue

  If (RAW_v < pav * StepSizeCutoff) Or (RAW_v > pav * (2 - StepSizeCutoff)) Then
    Dim diff As Double = System.Math.Abs(Decimal.Parse(RAW_v - RAW_pv))
    If diff < RAW_pv * (1 - StepSizeCutoff) Then
      pav = pav + (RAW_v - RAW_pv)
    End If
    RAW_v = pav
  End If
End If

Return RAW_v

Limit input values to be between min and max values

CODE
'Also enable advanced settings if needed, e.g. sum over one day to get output as the sum of
'the input samples during one day with the sum limited to the min & max values given.
Dim InputData As Input = Inputs.Precipitation #0 mm
Dim CutoffMax As Double = 90
Dim CutoffMin As Double = 0
Dim ResetValue As Double = 0

'Scale inputs as needed
Dim InputDataScaled As Double = InputData.Value * 1

InputDataScaled = if(InputDataScaled > CutoffMax, ResetValue, InputDataScaled)
InputDataScaled = if(InputDataScaled < CutoffMin, ResetValue, InputDataScaled)

Return InputDataScaled

Level measurement

Calculate the height of a liquid using two external pressure sensor inputs (air & liquid)

CODE

'Linear offset in mm
Const Offset_mm As Double = 0

'Inputs for air and water pressures; set next constants to scale these to the correct unit of measures
Dim airPressureRaw = Inputs.MAC - BaroTROLL (0-30psi)
Dim liquidPressureRaw = Inputs.MAS - LevelTROLL 400 (0-30psi)

'Factors to convert raw pressure values to Pascal (Pa/mmHg = 133.322; Pa/H2O = 9.80665; Pa/PSI = 6894.76; Pa/Atm = 101325)
Const airPressureRawToPa As Double = 133.322
Const liquidPressureRawToPa As Double = 6894.76

'The pressure offset of the sensors in Pascal; if the reported value is lower than it should be then the offset is negative
Const airPressureOffset_Pa As Double = -101325
Const liquidPressureOffset_Pa As Double = 0

'Factor to convert height in mm to the desired unit (ft/mm = 0.00328084; in/mm = 0.0393701)
Const outputScaling_mmToUnit As Double = 0.00328084

'Density of liquid being measured as kg/m^3 (water = 998)
Const density As Double = 998

'Convert everything to Pascal
Dim airPressure_Pa as Double = airPressureRaw.Value * airPressureRawToPa
Dim liquidPressure_Pa as Double = liquidPressureRaw.Value * liquidPressureRawToPa

'Liquid height = (pressure of liquid - pressure of air) / (density * acceleration of gravity) ; [Pa / (kg/m^3 * m/s^2) = m]; Pa = kg/m.s^2
Dim liquidHeight_mm As Double = ((((liquidPressure_Pa - liquidPressureOffset_Pa) - (airPressure_Pa - airPressureOffset_Pa)) / (density * 9.80665))) * 1000 + Offset_mm

Return liquidHeight_mm * outputScaling_mmToUnit

Calculate the height of a liquid using one air pressure sensor and raw ADC value of liquid sensor

CODE
'Linear offset in mm
Const Offset_mm As Double = 0

'Inputs for air and water pressures; set next constants to scale these to the correct unit of measures
Dim airPressureRaw = Inputs.MAC - BaroTROLL (0-30psi)
Dim liquidPressureRaw = Inputs.MAS - LevelTROLL 400 (0-30psi)

'Factors to convert raw pressure values to Pascal (Pa/mmHg = 133.322; Pa/H2O = 9.80665; Pa/PSI = 6894.76; Pa/Atm = 101325)
Const airPressureRawToPa As Double = 133.322
Const liquidPressureRawToPa As Double = 6894.76

'The pressure offset of the sensors in Pascal; if the reported value is lower than it should be then the offset is negative
Const airPressureOffset_Pa As Double = -101325
Const liquidPressureOffset_Pa As Double = 0

'Factor to convert height in mm to the desired unit (ft/mm = 0.00328084; in/mm = 0.0393701)
Const outputScaling_mmToUnit As Double = 0.00328084

'Density of liquid being measured as kg/m^3 (water = 998)
Const density As Double = 998

'Convert everything to Pascal
Dim airPressure_Pa as Double = airPressureRaw.Value * airPressureRawToPa
Dim liquidPressure_Pa as Double = liquidPressureRaw.Value * liquidPressureRawToPa

'Liquid height = (pressure of liquid - pressure of air) / (density * acceleration of gravity) ; [Pa / (kg/m^3 * m/s^2) = m]; Pa = kg/m.s^2
Dim liquidHeight_mm As Double = ((((liquidPressure_Pa - liquidPressureOffset_Pa) - (airPressure_Pa - airPressureOffset_Pa)) / (density * 9.80665))) * 1000 + Offset_mm

Return liquidHeight_mm * outputScaling_mmToUnit

Water depth to volume calculation (reservoir, dam, pond)

inlineImage.png
  1. Make your height to volume table

  2. Add new CI to the logger by clicking "Add Sensor" and searching for "Calculations & Agronomic Derivations", then click "Use"

  3. Select Input Type = "Piecewise function", select your level/depth input, edit the name of the new input (eg Water Volume), then click Add Sensor To Site.

  4. The new CI will be added to your site.

  5. Edit the CI: 

    1. Enter your depth (x) to volume (y) as a list of {x,y} (Blue highlight)

    2. Add any depth offsets as needed (yellow highlight)

    3. Set the output unit to the one corresponding to the y values in the {x,y} list

    4. Save the CI

  6. Make your height to volume table

  7. Add new CI to the logger by clicking "Add Sensor" and searching for "Calculations & Agronomic Derivations", then click "Use"

  8. Select Input Type = "Piecewise function", select your level/depth input, edit the name of the new input (eg Water Volume), then click Add Sensor To Site.

  9. The new CI will be added to your site.

  10. Edit the CI: 

    1. Enter your depth (x) to volume (y) as a list of {x,y} (Blue highlight)

    2. Add any depth offsets as needed (yellow highlight)

    3. Set the output unit to the one corresponding to the y values in the {x,y} list

    4. Save the CI

Weather

Vapour Pressure from RH and T

CODE
'Returns vapour pressure as kPa
'For more detail see
' https://outpost.atlassian.net/wiki/x/SID_Ag
' https://outpost.atlassian.net/wiki/x/5YB-/

Dim TemperatureIn As Input = Inputs.#a *CI Temperature °C
Dim HumidityIn As Input = Inputs.#a *CI Relative Humidity %

'Convert humidity to a percentage value; * 1 if already a %
Dim RH As Double = HumidityIn.Value * 1

'Specify the UOM of the input temperature
' C = °C; F = °F; K = Kelvin
Const UOM_In As String = "C"

'--------------------------------------------------------------------

Dim T As Double = TemperatureIn.Value

'Convert input temperature to °C
Select Case UOM_In
  Case "C" ' no conversion needed
  Case "F"
    T = (T - 32) * (5 / 9)
  Case "K"
    T = T - 273.15
  Case Else
    Return -273 ' Invalid UOM; please specify a valid UOM
End Select

Dim VapourPressure As Double = (RH / 100) * (0.6108 * System.math.exp((17.27 * T) / (T + 237.3)))

Return VapourPressure

Dew point temperature

CODE
'Derived dew point temperature
'https://www.ajdesigner.com/phphumidity/dewpoint_equation_dewpoint_temperature.php

Dim T_Input As Input = Inputs.#a *CI Air Temperature
Dim RH_Input As Input = Inputs.#a *CI Relative Humidity

' multiplier to convert RH to a decimal value; 0.01 if RH is a percentage
Const RhScaling As Double = 0.01

'C, F, or K
Const InputUom As String = "F"
Const OutputUom As String = "F"

'-----------------------------------------------------------

Dim T As Double = T_Input.Value

' Convert to C
Select Case InputUom
  Case "C"
   T = T
  Case "F"
   T = (T - 32) * 5 / 9
  Case "K"
   T = T - 273.15
  Case Else
   T = -1000 ' Invalid UOM; please specify a valid UOM
End Select

'RH must be a decimal; divide by 100 if it is a percentage
Dim RH As Double = RH_Input.Value * RhScaling

Dim T_Dp = (RH^(1/8)) * (112 + (0.9 * T)) + (0.1 * T) - 112

'convert from C to specified UOM
Select Case OutputUom
  Case "C"
   T_Dp = T_Dp
  Case "F"
   T_Dp = T_Dp * 9 / 5 + 32
  Case "K"
   T_Dp = T_Dp + 273.15
End Select

return T_Dp

Wind chill temperature

CODE
' Output is in the same unit as the input temperature

Dim WindTemperatureInput As Input = Inputs.Temperature
Dim WindSpeedInput As Input = Inputs.WindSpeed

'For more detail see:
' - https://en.wikipedia.org/wiki/Wind_chill
' - https://www.weather.gov/epz/wxcalc_windchill
' - https://www.weather.gov/media/epz/wxcalc/windChill.pdf

'Specify the UOM of the input temperature
' C = °C; F = °F; K = Kelvin
Const UOM_In As String = "C"

' Factor to convert input wind speed to mile/h
' m/s = 2.23694
' mile/h = 1
Const SpeedScalingFactor As Double = 2.23694

'-------------------------------------------------------------

Dim T As Double = WindTemperatureInput.Value
Dim V As Double = WindSpeedInput.Value * SpeedScalingFactor

'Convert input temperature to °F
Select Case UOM_In
  Case "C" ' no conversion needed
   T = T * 9 / 5 + 32
  Case "F"
  Case "K"
   T = (T - 273.15) * 9 / 5 + 32
  Case Else
   Return -273 ' Invalid UOM; please specify a valid UOM
End Select

Dim TChill As Double = T
' The wind chill formula is only valid <= 50°F (10°C) and wind speeds >= 3 mph (1.34 m/s).
If ((V >= 3) And (T <= 50))
  TChill = 35.74 + (0.6215 * T) - (35.75 * (V^0.16)) + (0.4275 * T * (V^0.16))
End If

'Convert output to same unit as input
Select Case UOM_In
  Case "C"
   TChill = (TChill - 32) * 5 / 9
  Case "F"
  Case "K"
   TChill = (TChill - 32) * 5 / 9 + 273.15
End Select

Return TChill

Filter for step, min & max limits, e.g. rain & wind

CODE
'Remove single point steps and samples outside min & max limits.
'Invalid samples are replace with the previous value

Dim dataIn As Input = Inputs.Wind Speed in m/s

Const SCALING As Double = 1 ' m/s to mph : 2.23694
Const MAX_VALUE As Double = 115 ' max wind speed ever = 103 m/s; maximum wind gust = 113 m/s
Const MIN_VALUE As Double = 0 ' wind & rain cannot be negative
Const MAX_STEP As Double = 115 ' this would depend on the sampling rate, maximum rate of change, etc.; Todo: consider sampling rate in calculations

'------------------------------

Dim dataOutVal As Double = dataIn.Value * SCALING

If PreviousValue.HasValue AndAlso dataIn.Previousvalue.HasValue Then
  Dim dataOutPrevVal As Double? = PreviousValue
  Dim dataPrevVal As Double? = dataIn.Previousvalue * SCALING

  Dim change = System.Math.Abs(Decimal.Parse(dataPrevVal - dataOutVal))

  If (dataOutVal > MAX_VALUE) Or (dataOutVal < MIN_VALUE) Or (change > MAX_STEP) Then
   dataOutVal = dataOutPrevVal
  End If

End If

Return dataOutVal

 

Common Mistakes

Calculated Input with formula that returns Nothing in the code path.

The CI will stop calculating if more than a certain number (10000) of consecutive calculations return Nothing. E.g.:

CODE
If <condition> Then Return <value> Else Return Nothing End If 'This CI will stop calculating when Nothing is returned 10000 times in a row

No null check when referencing a previous values.

The previous value is always null during calculation of the first data point. This need to be handled explicitly in the code if the formula needs to references the previous value. E.g.:

CODE
If Inputs.Input A.PreviousValue.HasValue Then Return <somevalue> Else Return <othervalue>

Source input not logging

Calculated input uses the logging frequency of the inputs it references to align the data points. Currently it will not work if one of the referenced inputs is set to not logging.

 

References about Visual Basic

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.