An005 Lua BACNET Client Operations

download An005 Lua BACNET Client Operations

of 8

Transcript of An005 Lua BACNET Client Operations

  • 8/10/2019 An005 Lua BACNET Client Operations

    1/8

    SmartStruxure Lite

    Solution

    Application NotesAN005 - Lua BACnet Client Operations

    Get Control. Get Efficient. Get Value TM

  • 8/10/2019 An005 Lua BACNET Client Operations

    2/8

    AN005 - Lua BACnet Client OperationsApplication Notes AN005 2

    Schneider Electric- Small Building Systems Tel. Americas: North Andover, MA 1-800-225 -0962 Tel. Europe: Malm, Sweden +46 40 38 68 50 Tel. Asia Pacific: Hong Kong +852 2565 0621 Product Name AN005 - Lua BACnet Client Operations - 02 www.schneider-electric.com/buildings October 2013 ct

    2

    0 1 3 S c

    h n e

    i d e r

    E l e c

    t r i c

    . A l l r i g

    h t s r e s e r v e

    d .

    A l l b r a n

    d n a m e s ,

    t r a d

    e m a r k s ,

    a n

    d r e g

    i s t e r e

    d t r a

    d e m a r k s a r e

    t h e p r o p e r

    t y o

    f

    t h e

    i r r e s p e c

    t i v e o

    w n e r s .

    I n f o r m a

    t i o n c o n

    t a i n e

    d w

    i t h i n t h i s d o c u m e n t

    i s s u

    b j e c

    t t o c

    h a n g e w

    i t h o u

    t n o

    t i c e .

    Introduction and ContextWhen integrating SmartStruxure Lite Managers with third-party devices, sometimes aBACnet client functionality can be useful. This application note gives an overview of the fourbasic Lua functions to access remote BACnet points.

    Note that all SmartStruxure Lite Managers have full BACnet server capabilities, howeverthe BACnet client functionality is currently only available through Lua. Also, with the currentbasic client capabilities, the maximum number of devices supported on a single BACnetnetwork is 1000.

    NOTE: If using BACnet client tools in version 2.6.x or later, it is necessary to modify yourscript to prevent BACnet communication from starting 90 seconds after the controllerinitialization.

    This can be done by encapsulating your script logic within the fo llowing loop:

    if scl.sysclock() > 90 then

    Case 1: Four Lines The three basic BACnet commands that can be performed are who-is, read and wri terequests for speci points. A fourth function is available to obtain the resulting value of aread request.

    The below shows a simple four-line script that does a who-is , reads a value, displays thevalue, does a write.

    bacnet.whois(500, 500)

    bacnet.read(500, AV1)

    print(bacnet.value())

    bacnet.write(500, AV1, 32)

  • 8/10/2019 An005 Lua BACNET Client Operations

    3/8

    AN005 - Lua BACnet Client OperationsApplication Notes AN005 3

    Schneider Electric- Small Building Systems Tel. Americas: North Andover, MA 1-800-225 -0962 Tel. Europe: Malm, Sweden +46 40 38 68 50 Tel. Asia Pacific: Hong Kong +852 2565 0621 Product Name AN005 - Lua BACnet Client Operations - 02 www.schneider-electric.com/buildings October 2013 ct

    2

    0 1 3 S c

    h n e

    i d e r

    E l e c

    t r i c

    . A l l r i g

    h t s r e s e r v e

    d .

    A l l b r a n

    d n a m e s ,

    t r a d

    e m a r k s ,

    a n

    d r e g

    i s t e r e

    d t r a

    d e m a r k s a r e

    t h e p r o p e r

    t y o

    f

    t h e

    i r r e s p e c

    t i v e o

    w n e r s .

    I n f o r m a

    t i o n c o n

    t a i n e

    d w

    i t h i n t h i s d o c u m e n t

    i s s u

    b j e c

    t t o c

    h a n g e w

    i t h o u

    t n o

    t i c e .

    Step 2: Step-by-Step Process The below shows a more thorough step-by-step example on how to access a remote BACnetdevice point in Lua.

    if scl.sysclock() > 90 then

    if whois ~= true then

    bacnet.whois(500, 500) -- Step one: who is? (device or range)

    whois = true -- Next run: skip to step two

    elseif fetch ~= 0 then

    fetch = bacnet.read(500, AV1) -- Step two: read! (specic point)

    else

    value, stamp = bacnet.value() -- Step three: check value and time

    if old_stamp ~= stamp then -- If time differs: value has changed!

    old_stamp = stamp -- Keep track of time stamp

    print(DEV500.AV1:, value) -- Optional: display the changed value

    ME.AV2_Present_Value.value = value -- Optional: keep value locally

    end

    fetch = false -- Next run: go back to step two (to read again)

    end

    end

  • 8/10/2019 An005 Lua BACNET Client Operations

    4/8

    AN005 - Lua BACnet Client OperationsApplication Notes AN005 4

    Schneider Electric- Small Building Systems Tel. Americas: North Andover, MA 1-800-225 -0962 Tel. Europe: Malm, Sweden +46 40 38 68 50 Tel. Asia Pacific: Hong Kong +852 2565 0621 Product Name AN005 - Lua BACnet Client Operations - 02 www.schneider-electric.com/buildings October 2013 ct

    2

    0 1 3 S c

    h n e

    i d e r

    E l e c

    t r i c

    . A l l r i g

    h t s r e s e r v e

    d .

    A l l b r a n

    d n a m e s ,

    t r a d

    e m a r k s ,

    a n

    d r e g

    i s t e r e

    d t r a

    d e m a r k s a r e

    t h e p r o p e r

    t y o

    f

    t h e

    i r r e s p e c

    t i v e o

    w n e r s .

    I n f o r m a

    t i o n c o n

    t a i n e

    d w

    i t h i n t h i s d o c u m e n t

    i s s u

    b j e c

    t t o c

    h a n g e w

    i t h o u

    t n o

    t i c e .

    Case 3: More OptionsFor a simpler way to change the remote BACnet point specications, another example isprovided below. This Lua uses two top variables to specify the remote device instance andthe object name.

    if scl.sysclock() > 90 then

    dev_inst = 500 -- Device instanceobj_name = AV1 -- Object type and number

    if whois ~= true then

    bacnet.whois(dev_inst, dev_inst) -- Step one: who is? (device or range)

    whois = true -- Next run: skip to step two

    elseif fetch ~= 0 then

    fetch = bacnet.read(dev_inst, obj_name) -- Step two: read! (specic point)

    else

    value, stamp = bacnet.value() -- Step three: check value and time

    if old_stamp ~= stamp then -- If time differs: value has changed!old_stamp = stamp -- Keep track of time stamp

    -- Optional: display the changed value

    print(DEV .. dev_inst .. . .. obj_name .. :, value)

    ME.AV2_Present_Value.value = value -- Optional: keep value locally

    bacnet.write(dev_inst, obj_name, value + 1) -- Optional: increase value by +1

    end

    fetch = false -- Next run: go back to step two (to read again)

    end

    endSimply changing the dev_inst and obj_name variables will sufce in using the script in real-lifesituations.

    Note that as an additional step, the above script example is also writing to the remote object. This means that every time the script is executed (e.g. every few seconds), the remotevalue will be incremented and read back again. As a result, the last optional lines should beadjusted for the specic needs of the integrator.

  • 8/10/2019 An005 Lua BACNET Client Operations

    5/8

    AN005 - Lua BACnet Client OperationsApplication Notes AN005 5

    Schneider Electric- Small Building Systems Tel. Americas: North Andover, MA 1-800-225 -0962 Tel. Europe: Malm, Sweden +46 40 38 68 50 Tel. Asia Pacific: Hong Kong +852 2565 0621 Product Name AN005 - Lua BACnet Client Operations - 02 www.schneider-electric.com/buildings October 2013 ct

    2

    0 1 3 S c

    h n e

    i d e r

    E l e c

    t r i c

    . A l l r i g

    h t s r e s e r v e

    d .

    A l l b r a n

    d n a m e s ,

    t r a d

    e m a r k s ,

    a n

    d r e g

    i s t e r e

    d t r a

    d e m a r k s a r e

    t h e p r o p e r

    t y o

    f

    t h e

    i r r e s p e c

    t i v e o

    w n e r s .

    I n f o r m a

    t i o n c o n

    t a i n e

    d w

    i t h i n t h i s d o c u m e n t

    i s s u

    b j e c

    t t o c

    h a n g e w

    i t h o u

    t n o

    t i c e .

    Case 4: Reading Multiple Devices and CharactersWhen many BACnet remote points need to be read, the below lus function can be used.

    This Lua loops through a list of device instances and object names.

    if scl.sysclock() > 90 then

    obj_list = { -- Local and remote objects list

    AV21 = {600, AV1},

    AV22 = {700, AV2},

    AV23 = {800, AV3}}

    if whois ~= true then

    bacnet.whois(600, 800) -- Step one: who is? (devices range)

    whois = true -- Next run: skip to step two

    elseif fetch ~= 0 then

    obj_link, obj_info = next(obj_list, obj_link) -- Find next objects pair

    if obj_link == nil then -- Loop around on last pair

    obj_link, obj_info = next(obj_list, obj_link)

    end

    dev_inst = obj_info[1]

    obj_name = obj_info[2]

    fetch = bacnet.read(dev_inst, obj_name) -- Step two: read request!

    if fetch ~= 0 then -- On error: print message

    print(BACnet read failure on DEV .. dev_inst .. . .. obj_name)

    else

    old_value, old_stamp = bacnet.value() -- Reset the timeout

    end

    else

    value, stamp = bacnet.value() -- Step three: check value and time

    if old_stamp ~= stamp then -- If time differs: value has changed!

    ME[obj_link .. _Present_Value].value = value -- Update value

    print(string.sub(os.date(), 10, 17), ME. .. obj_link,

    DEV .. dev_inst .. . .. obj_name, value) -- Display value

    elseif scl.sysclock() - old_stamp > 3 then -- Timeout after 3 seconds

    print(BACnet read timeout on DEV .. dev_inst .. . .. obj_name)

    end

    fetch = false -- Next run: read next object in list

    end

    end

    Simply adjusting the obj_list table content should sufce in using the script in real-lifesituations. This specic example fetches three remote points (DEV600.AV1, DEV600.AV2,and DEV600.AV3) from three different remote BACnet devices. It then stores the resultsinto local analog values (ME.AV21, ME.AV22, and ME.AV23).

    Note the resulting update period for those variables is twice the PG script period,multiplied by the number of remote objects actively fetched. In this case, since the script

    is running every second, and because three objects are read, the resulting typical objectupdate period is every 6 seconds (1 2 3).

  • 8/10/2019 An005 Lua BACNET Client Operations

    6/8

    AN005 - Lua BACnet Client OperationsApplication Notes AN005 6

    Schneider Electric- Small Building Systems Tel. Americas: North Andover, MA 1-800-225 -0962 Tel. Europe: Malm, Sweden +46 40 38 68 50 Tel. Asia Pacific: Hong Kong +852 2565 0621 Product Name AN005 - Lua BACnet Client Operations - 02 www.schneider-electric.com/buildings October 2013 ct

    2

    0 1 3 S c

    h n e

    i d e r

    E l e c

    t r i c

    . A l l r i g

    h t s r e s e r v e

    d .

    A l l b r a n

    d n a m e s ,

    t r a d

    e m a r k s ,

    a n

    d r e g

    i s t e r e

    d t r a

    d e m a r k s a r e

    t h e p r o p e r

    t y o

    f

    t h e

    i r r e s p e c

    t i v e o

    w n e r s .

    I n f o r m a

    t i o n c o n

    t a i n e

    d w

    i t h i n t h i s d o c u m e n t

    i s s u

    b j e c

    t t o c

    h a n g e w

    i t h o u

    t n o

    t i c e .

    Case 5: Full Read and Write ScriptIn a situation where some points need to be updated more often than others, an extratime condition can be used to only perform read operations when required. On top of theread interval, the below example script adds the ability to specify which objects should bewritten when their value changes.

    -- *** Variables Initialization ***

    if scl.sysclock() > 90 then

    if var_init == nil then

    var_init = true

    -- Local and remote objects list, in the format:

    -- LocalObject = {RemoteDevice, RemoteObject, ReadSecs, Write, KeptValue, KeptSecs}

    obj_list = {

    AV21 = {600, AV1, 10 , false, 0, 0}, -- Read DEV600.AV1 every 10s into AV21

    AV22 = {700, AV2, 10 , false, 0, 0}, -- Read DEV700.AV2 every 10s into AV22

    AV23 = {800, AV3, 30 , true, 0, 0}} - - Read every 10s, write if AV23 changes

    -- This is just a quick function to print with a timestamp:

    function display(...) print(os.date():sub(10, 17), ...) end

    end

    -- *** Program Execution ***

    if whois ~= true then

    bacnet.whois(600, 800) -- Step one: who is? (devices range)

    whois = true -- Next run: skip to step two

    ecount = 0 -- Reset the error count

    display(Sending who-is...)

    elseif fetch ~= 0 then

    repeat

    obj_link, obj_info = next(obj_list, obj_link) -- Find next pair

    if obj_link == nil then -- Loop around

    obj_link, obj_info = next(obj_list, obj_link)

    end

    obj_item = ME[obj_link .. _Present_Value] -- Keep object pointer

    -- Read condition, when time interval has elapsed:

    obj_read = (scl.sysclock() - obj_item.time > obj_info[3])

  • 8/10/2019 An005 Lua BACNET Client Operations

    7/8

    AN005 - Lua BACnet Client OperationsApplication Notes AN005 7

    Schneider Electric- Small Building Systems Tel. Americas: North Andover, MA 1-800-225 -0962 Tel. Europe: Malm, Sweden +46 40 38 68 50 Tel. Asia Pacific: Hong Kong +852 2565 0621 Product Name AN005 - Lua BACnet Client Operations - 02 www.schneider-electric.com/buildings October 2013 ct

    2

    0 1 3 S c

    h n e

    i d e r

    E l e c

    t r i c

    . A l l r i g

    h t s r e s e r v e

    d .

    A l l b r a n

    d n a m e s ,

    t r a d

    e m a r k s ,

    a n

    d r e g

    i s t e r e

    d t r a

    d e m a r k s a r e

    t h e p r o p e r

    t y o

    f

    t h e

    i r r e s p e c

    t i v e o

    w n e r s .

    I n f o r m a

    t i o n c o n

    t a i n e

    d w

    i t h i n t h i s d o c u m e n t

    i s s u

    b j e c

    t t o c

    h a n g e w

    i t h o u

    t n o

    t i c e .

    -- Write conditions:

    obj_write = (obj_info[4] -- When writeable, and:

    and ((obj_info[5] ~= obj_item.value) -- Either value changed

    or (obj_info[6] ~= obj_item.time))) -- Or timestamp changed

    until obj_read or obj_write -- Loop until read or write has been found...

    -- Step two: read or write request!if obj_write then

    display(ME. .. obj_link .. DEV .. obj_info[1]

    .. . .. obj_info[2] .. write: .. obj_item.value)

    bacnet.write(obj_info[1], obj_info[2], obj_item.value) -- Write value

    obj_info[5] = obj_item.value -- Keep last object value

    obj_info[6] = obj_item.time -- Keep last object time

    else

    fetch = bacnet.read(obj_info[1], obj_info[2]) -- Read at time interval

    if fetch ~= 0 then -- On error: print messagedisplay(BACnet read failure on DEV .. obj_info[1] .. . .. obj_info[2])

    else

    old_value, old_stamp = bacnet.value() -- Reset the timeout

    end

    end

    else

    value, stamp = bacnet.value() -- Step three: check value and time

    if old_stamp ~= stamp then -- If time differs: value has changed!

    obj_item.value = value -- Update valueobj_info[5] = obj_item.value -- Keep last object value

    obj_info[6] = obj_item.time -- Keep last object time

    display(ME. .. obj_link .. DEV .. obj_info[1]

    .. . .. obj_info[2] .. read: .. value)

    ecount = 0 -- Reset the error count

    elseif scl.sysclock() - old_stamp > 3 then -- Timeout after 3 seconds

    display(BACnet read timeout on DEV .. obj_info[1] .. . .. obj_info[2])

    -- Send another who-is? after 3 read errors:

    ecount = ecount + 1if ecount >= 3 then

    whois = false

    end

    end

    fetch = false -- Next run: read next object in list

    end

    end

  • 8/10/2019 An005 Lua BACNET Client Operations

    8/8

    AN005 - Lua BACnet Client OperationsApplication Notes AN005 8

    Schneider Electric- Small Building Systems Tel. Americas: North Andover, MA 1-800-225 -0962 Tel. Europe: Malm, Sweden +46 40 38 68 50 Tel. Asia Pacific: Hong Kong +852 2565 0621 Product Name AN005 - Lua BACnet Client Operations - 02 www.schneider-electric.com/buildings October 2013 ct

    2

    0 1 3 S c

    h n e

    i d e r

    E l e c

    t r i c

    . A l l r i g

    h t s r e s e r v e

    d .

    A l l b r a n

    d n a m e s ,

    t r a d

    e m a r k s ,

    a n

    d r e g

    i s t e r e

    d t r a

    d e m a r k s a r e

    t h e p r o p e r

    t y o

    f

    t h e

    i r r e s p e c

    t i v e o

    w n e r s .

    I n f o r m a

    t i o n c o n

    t a i n e

    d w

    i t h i n t h i s d o c u m e n t

    i s s u

    b j e c

    t t o c

    h a n g e w

    i t h o u

    t n o

    t i c e .

    Simply adjusting the obj_list table content should sufce in using that script in real-lifesituations. The above example fetches three remote points (DEV600.AV1, DEV600.AV2,and DEV600.AV3) from three different remote BACnet devices. It then stores the results intolocal analog values (ME.AV21, ME.AV22, and ME.AV23). It performs the read requests at thespecied ReadSecs interval for each object (10 seconds, 10 seconds, and 30

    seconds).

    This script a lso writes back, when specied, the object value when it changes, (in the aboveexample), only if the third line of the if obj_list table has its Write parameter set to true, whichwill write ME.AV23, if changed, into DEV600.AV3). It then performs a BACnet write operationto the remote device, effectively sending out the new value.

    Note if the BACnet connectivity is completely lost, an error count gets incremented to triggeranother who-is request periodically (after every 3 failures) to effectively re-acquire the devicesonce the connectivity is restored.