Skip to content

BACnet Simulator Lua Script Tutorial

This tutorial will outline how to write a basic lua script to control the simulator. We will cover how to size object instances and add some logic to update present value properties in both the Run and Update functions.

Create Object Instances

function Run()
  bacnet.createAnalogInputs(1)
  bacnet.createAnalogValues(1)
  bacnet.createAnalogOutputs(1)

  bacnet.setAnalogInputName(0, "ANALOG_INPUT_0")
  bacnet.setAnalogValueName(0, "ANALOG_VALUE_0")
  bacnet.setAnalogOutputName(0, "ANALOG_OUTPUT_0")
end

This code will create 1 instance of Analog Input, Analog Output and Analog Value objects and set the object names for each of them.

Add Some Logic to the Run Function

As the Run function operates on its own thread separate from the main simulator thread, it can be kept running using the isBacnetRunning function with a while loop.

local increment = 0
local priority = 1
local mod = 15

function sleep(time)
    local duration = os.time() + time
    while os.time() < duration do end
end

function Run()
  bacnet.createAnalogInputs(1)
  bacnet.createAnalogValues(1)
  bacnet.createAnalogOutputs(1)

  bacnet.setAnalogInputName(0, "ANALOG_INPUT_0")
  bacnet.setAnalogValueName(0, "ANALOG_VALUE_0")
  bacnet.setAnalogOutputName(0, "ANALOG_OUTPUT_0")

  while isBacnetRunning() do
    increment = math.fmod (increment, mod) + 1
    bacnet.setAnalogValuePresentValue(0, increment, priority)
    sleep(1)
  end
end

Every second this logic will increment a value by 1, setting the present value of instance 0 of the Analog Value object. Once the value reaches 15 it will wrap around to 1 again. As lua does not provide a standard sleep function, one must be included.

Add Some Logic to the Update Function

The Update function will be run on every process cycle of the simulator. As this is called from the main simulator thread, there should be no logic in here that blocks execution, ie sleeps etc.

function Update()
  value = bacnet.getAnalogOutputPresentValue(0)
  bacnet.setAnalogInput(0, value, priority)
end

This logic will mirror whatever value that was written to the present value of the Analog Output object to the Analog Input instance.

Full code

local increment = 0
local priority = 1
local mod = 15

function sleep(time)
    local duration = os.time() + time
    while os.time() < duration do end
end

function Run()
  bacnet.createAnalogInputs(1)
  bacnet.createAnalogValues(1)
  bacnet.createAnalogOutputs(1)

  bacnet.setAnalogInputName(0, "ANALOG_INPUT_0")
  bacnet.setAnalogValueName(0, "ANALOG_VALUE_0")
  bacnet.setAnalogOutputName(0, "ANALOG_OUTPUT_0")

  while isBacnetRunning() do
    increment = math.fmod (increment, mod) + 1
    bacnet.setAnalogValuePresentValue(0, increment, priority)
    sleep(1)
  end
end

function Update()
  value = bacnet.getAnalogOutputPresentValue(0)
  bacnet.setAnalogInputPresentValue(0, value, priority)
end
Back to top