beremiz

merged Andrey's default

2018-08-08, Edouard Tisserant
53f3eb5c47f7
merged Andrey's default
  • +1 -0
    BeremizIDE.py
  • +1 -1
    IDEFrame.py
  • +46 -0
    PLCGenerator.py
  • +65 -60
    README.md
  • +0 -20
    controls/DebugVariablePanel/DebugVariablePanel.py
  • +202 -0
    tests/BACnet/bacnet_0@bacnet/bacnet_slave
  • +2 -0
    tests/BACnet/bacnet_0@bacnet/baseconfnode.xml
  • +2 -0
    tests/BACnet/bacnet_0@bacnet/confnode.xml
  • +4 -0
    tests/BACnet/beremiz.xml
  • +601 -0
    tests/BACnet/plc.xml
  • +6 -0
    tests/modbus/beremiz.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/ModbusRequest_0@ModbusRequest/baseconfnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/ModbusRequest_0@ModbusRequest/confnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/ModbusRequest_1@ModbusRequest/baseconfnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/ModbusRequest_1@ModbusRequest/confnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/baseconfnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/confnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/HoldingRegs@MemoryArea/baseconfnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/HoldingRegs@MemoryArea/confnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/InputRegs@MemoryArea/baseconfnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/InputRegs@MemoryArea/confnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/baseconfnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/confnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/baseconfnode.xml
  • +2 -0
    tests/modbus/modbus_0@modbus/confnode.xml
  • +314 -0
    tests/modbus/plc.xml
  • --- a/BeremizIDE.py Wed Aug 08 13:27:44 2018 +0200
    +++ b/BeremizIDE.py Wed Aug 08 13:46:19 2018 +0200
    @@ -739,6 +739,7 @@
    def RefreshStatusToolBar(self):
    StatusToolBar = self.Panes["StatusToolBar"]
    StatusToolBar.ClearTools()
    + StatusToolBar.SetMinSize(StatusToolBar.GetToolBitmapSize())
    if self.CTR is not None:
    --- a/IDEFrame.py Wed Aug 08 13:27:44 2018 +0200
    +++ b/IDEFrame.py Wed Aug 08 13:46:19 2018 +0200
    @@ -2164,9 +2164,9 @@
    self.Bind(wx.EVT_MENU, getattr(self, method), id=id)
    self.CurrentEditorToolBar.append(id)
    EditorToolBar.Realize()
    - self.AUIManager.GetPane("EditorToolBar").BestSize(EditorToolBar.GetBestSize())
    self.AUIManager.GetPane("EditorToolBar").Show()
    self.AUIManager.Update()
    + self.AUIManager.GetPane("EditorToolBar").BestSize(EditorToolBar.GetBestSize())
    elif menu is None:
    self.ResetEditorToolBar()
    self.CurrentMenu = menu
    --- a/PLCGenerator.py Wed Aug 08 13:27:44 2018 +0200
    +++ b/PLCGenerator.py Wed Aug 08 13:46:19 2018 +0200
    @@ -900,6 +900,42 @@
    for connection in related:
    self.ConnectionTypes[connection] = var_type
    + def GetUsedEno(self, body, connections):
    + """
    + Function checks whether value on given connection
    + comes from block, that has used EN input and
    + returns variable name for ENO output.
    +
    + This is needed to avoid value propagation from blocks
    + with false signal on EN input.
    +
    + :param body:
    + body of the block for that program is currently generated
    + :param connections:
    + connection, that's source is checked for EN/ENO usage
    + :return:
    + if EN/ENO are not used, then None is returned
    + Otherwise BOOL variable corresponding to ENO
    + output is returned.
    + """
    +
    + if len(connections) != 1:
    + return None
    + ref_local_id = connections[0].getrefLocalId()
    + blk = body.getcontentInstance(ref_local_id)
    + if blk is None:
    + return None
    +
    + for invar in blk.inputVariables.getvariable():
    + if invar.getformalParameter() == "EN":
    + if len(invar.getconnectionPointIn().getconnections()) > 0:
    + if blk.getinstanceName() is None:
    + var_name = "%s%d_ENO" % (blk.gettypeName(), blk.getlocalId())
    + else:
    + var_name = "%s.ENO" % blk.getinstanceName()
    + return var_name
    + return None
    +
    def ComputeProgram(self, pou):
    body = pou.getbody()
    if isinstance(body, ListType):
    @@ -958,11 +994,21 @@
    if connections is not None:
    expression = self.ComputeExpression(body, connections)
    if expression is not None:
    + eno_var = self.GetUsedEno(body, connections)
    + if eno_var is not None:
    + self.Program += [(self.CurrentIndent + "IF %s" % eno_var, ())]
    + self.Program += [(" THEN\n ", ())]
    + self.IndentRight()
    +
    self.Program += [(self.CurrentIndent, ()),
    (instance.getexpression(), (self.TagName, "io_variable", instance.getlocalId(), "expression")),
    (" := ", ())]
    self.Program += expression
    self.Program += [(";\n", ())]
    +
    + if eno_var is not None:
    + self.IndentLeft()
    + self.Program += [(self.CurrentIndent + "END_IF;\n", ())]
    elif isinstance(instance, BlockClass):
    block_type = instance.gettypeName()
    self.ParentGenerator.GeneratePouProgram(block_type)
    --- a/README.md Wed Aug 08 13:27:44 2018 +0200
    +++ b/README.md Wed Aug 08 13:46:19 2018 +0200
    @@ -8,89 +8,94 @@
    With Beremiz, you conform to standards, avoid vendor lock, and contribute to the better future of Automation.
    +Beremiz consists of two components:
    +
    +* Integrated Development Environment (IDE), [Beremiz.py](https://bitbucket.org/automforge/beremiz/src/tip/Beremiz.py?at=default). It's running on user's computer and is used to write/compile/debug PLC programs and control PLC runtime.
    +* Reference runtime implementation in python, [Beremiz_service.py](https://bitbucket.org/automforge/beremiz/src/tip/Beremiz_service.py?at=default). It's running on target platform, communicates with I/O and executes PLC program.
    +
    See official [Beremiz website](http://www.beremiz.org/) for more information.
    -### Build on Linux ###
    +## Build on Linux ##
    * Prerequisites
    -```
    -#!sh
    -* # Ubuntu/Debian :
    -sudo apt-get install build-essential bison flex autoconf
    -sudo apt-get install python-wxgtk3.0 pyro mercurial
    -sudo apt-get install python-nevow python-matplotlib python-lxml python-zeroconf python-cycler
    -```
    + # Ubuntu/Debian :
    + sudo apt-get install build-essential bison flex autoconf
    + sudo apt-get install python-wxgtk3.0 pyro mercurial
    + sudo apt-get install python-nevow python-matplotlib python-lxml python-zeroconf python-cycler
    +
    * Prepare
    -```
    -#!sh
    -mkdir ~/Beremiz
    -cd ~/Beremiz
    -```
    +
    + mkdir ~/Beremiz
    + cd ~/Beremiz
    * Get Source Code
    -```
    -#!sh
    -cd ~/Beremiz
    -hg clone https://bitbucket.org/skvorl/beremiz
    -hg clone https://bitbucket.org/mjsousa/matiec
    -```
    + cd ~/Beremiz
    + hg clone https://bitbucket.org/skvorl/beremiz
    + hg clone https://bitbucket.org/mjsousa/matiec
    * Build MatIEC compiler
    -```
    -#!sh
    -cd ~/Beremiz/matiec
    -autoreconf -i
    -./configure
    -make
    -```
    +
    + cd ~/Beremiz/matiec
    + autoreconf -i
    + ./configure
    + make
    +
    +* Build CanFestival (optional)
    + Only needed for CANopen support. Please read CanFestival manual to choose CAN interface other than 'virtual'.
    -* Build CanFestival (optional)
    -Only needed for CANopen support. Please read CanFestival manual to choose CAN interface other than 'virtual'.
    + cd ~/Beremiz
    + hg clone http://dev.automforge.net/CanFestival-3
    + cd ~/Beremiz/CanFestival-3
    + ./configure --can=virtual
    + make
    -```
    -#!sh
    -cd ~/Beremiz
    -hg clone http://dev.automforge.net/CanFestival-3
    +* Build Modbus library (optional)
    + Only needed for Modbus support.
    -cd ~/Beremiz/CanFestival-3
    -./configure --can=virtual
    -make
    -```
    + cd ~/Beremiz
    + hg clone https://bitbucket.org/mjsousa/modbus Modbus
    + cd ~/Beremiz/Modbus
    + make
    * Launch Beremiz IDE
    -```
    -#!sh
    -cd ~/Beremiz/beremiz
    -python Beremiz.py
    -```
    + cd ~/Beremiz/beremiz
    + python Beremiz.py
    +
    +## Run standalone Beremiz runtime ##
    -### Run standalone Beremiz service ###
    +Runtime implementation can be different on different platforms.
    +For example, PLC used Cortex-M most likely would have C-based runtime. Beremiz project contains reference implementation in python, that can be easily run on GNU/Linux, Windows and Mac OS X.
    +This section will describe how to run it.
    +
    +If project's URL is 'LOCAL://', then IDE launches temprorary instance of Beremiz python runtime (Beremiz_service.py) localy as user tries to connect to PLC. This allows to debug programs localy without PLC.
    +
    +If you want to run Beremiz_service.py as standalone service, then follow these instructions:
    * Start standalone Beremiz service
    -```
    -#!sh
    -cd ~/Beremiz
    -mkdir beremiz_workdir
    -cd ~/beremiz
    -python Beremiz_service.py -p 61194 -i localhost -x 0 -a 1 ~/Beremiz/beremiz_workdir
    -```
    + cd ~/Beremiz
    + mkdir beremiz_workdir
    + cd ~/beremiz
    + python Beremiz_service.py -p 61194 -i localhost -x 0 -a 1 ~/Beremiz/beremiz_workdir
    * Launch Beremiz IDE
    -```
    -#!sh
    -cd ~/Beremiz/beremiz
    -python Beremiz.py
    -```
    -* Open/Create PLC project in Beremiz IDE.
    -*
    -Enter target location URI in project's settings (project->Config->BeremizRoot/URI_location) pointed to your running Beremiz service (For example, PYRO://127.0.0.1:61194).
    -Save project and connect to running Beremiz service.
    +
    + cd ~/Beremiz/beremiz
    + python Beremiz.py
    -### Documentation ###
    +* Open/Create PLC project in Beremiz IDE.
    + Enter target location URI in project's settings (project->Config->BeremizRoot/URI_location) pointed to your running Beremiz service (For example, PYRO://127.0.0.1:61194).
    + Save project and connect to running Beremiz service.
    +
    +## Examples ##
    +
    +Almost for all functionality exists example in ['tests'](https://bitbucket.org/automforge/beremiz/src/tip/tests/?at=default) directory.
    +Most of examples are shown on [Beremiz youtube channel](https://www.youtube.com/channel/UCcE4KYI0p1f6CmSwtzyg-ZA).
    +
    +## Documentation ##
    * See [Beremiz youtube channel](https://www.youtube.com/channel/UCcE4KYI0p1f6CmSwtzyg-ZA) to get quick information how to use Beremiz IDE.
    @@ -108,7 +113,7 @@
    * See official [Beremiz website](http://www.beremiz.org/) for more information.
    -### Support and development ###
    +## Support and development ##
    Main community support channel is [mailing list](https://sourceforge.net/p/beremiz/mailman/beremiz-devel/) (beremiz-devel@lists.sourceforge.net).
    --- a/controls/DebugVariablePanel/DebugVariablePanel.py Wed Aug 08 13:27:44 2018 +0200
    +++ b/controls/DebugVariablePanel/DebugVariablePanel.py Wed Aug 08 13:46:19 2018 +0200
    @@ -35,8 +35,6 @@
    import matplotlib
    matplotlib.use('WX') # noqa
    import matplotlib.pyplot
    -from matplotlib.backends.backend_wxagg import _convert_agg_to_wx_bitmap
    -
    from editors.DebugViewer import DebugViewer
    from util.BitmapLibrary import GetBitmap
    @@ -525,24 +523,6 @@
    def RefreshView(self):
    self.RefreshCanvasPosition()
    - width, height = self.GraphicsWindow.GetVirtualSize()
    - bitmap = wx.EmptyBitmap(width, height)
    - dc = wx.BufferedDC(wx.ClientDC(self.GraphicsWindow), bitmap)
    - dc.Clear()
    - dc.BeginDrawing()
    - if self.DraggingAxesPanel is not None:
    - destBBox = self.DraggingAxesBoundingBox
    - srcBBox = self.DraggingAxesPanel.GetAxesBoundingBox()
    -
    - srcBmp = _convert_agg_to_wx_bitmap(self.DraggingAxesPanel.get_renderer(), None)
    - srcDC = wx.MemoryDC()
    - srcDC.SelectObject(srcBmp)
    -
    - dc.Blit(destBBox.x, destBBox.y,
    - int(destBBox.width), int(destBBox.height),
    - srcDC, srcBBox.x, srcBBox.y)
    - dc.EndDrawing()
    -
    if not self.Fixed or self.Force:
    self.Force = False
    refresh_graphics = True
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/BACnet/bacnet_0@bacnet/bacnet_slave Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,202 @@
    +(dp0
    +S'BV_Obj'
    +p1
    +(lp2
    +sS'AV_Obj'
    +p3
    +(lp4
    +(dp5
    +S'loc'
    +p6
    +S'MD0_2'
    +p7
    +sS'Description'
    +p8
    +S''
    +p9
    +sS'Unit ID'
    +p10
    +I19
    +sS'Object Identifier'
    +p11
    +I0
    +sS'Ctype'
    +p12
    +S'float'
    +p13
    +sS'BACnetObjTypeID'
    +p14
    +I2
    +sS'Settable'
    +p15
    +S'Y'
    +p16
    +sS'Engineering Units'
    +p17
    +V(Energy) kilowatt-hours (19)
    +p18
    +sS'Object Name'
    +p19
    +VEnergyCounter
    +p20
    +sasS'AO_Obj'
    +p21
    +(lp22
    +(dp23
    +g6
    +S'QD0_1'
    +p24
    +sg8
    +V
    +p25
    +sS'Unit ID'
    +p26
    +I62
    +sS'Object Identifier'
    +p27
    +V0
    +p28
    +sg12
    +g13
    +sg14
    +I1
    +sg15
    +g16
    +sS'Object Name'
    +p29
    +VTemperatureSetPoint
    +p30
    +sS'Engineering Units'
    +p31
    +V(Temperature) degrees-celsius (62)
    +p32
    +sasS'MSI_Obj'
    +p33
    +(lp34
    +sS'BO_Obj'
    +p35
    +(lp36
    +(dp37
    +g6
    +S'QX0_4'
    +p38
    +sg8
    +g9
    +sS'Object Identifier'
    +p39
    +I2
    +sg12
    +S'uint8_t'
    +p40
    +sg14
    +I4
    +sg15
    +g16
    +sS'Object Name'
    +p41
    +VBlockClimateControl
    +p42
    +sasS'MSO_Obj'
    +p43
    +(lp44
    +sS'EDEfile_parm'
    +p45
    +(dp46
    +S'next_EDE_file_version'
    +p47
    +I1
    +ssS'BI_Obj'
    +p48
    +(lp49
    +(dp50
    +g6
    +S'IX0_3'
    +p51
    +sg8
    +g9
    +sS'Object Identifier'
    +p52
    +I0
    +sg12
    +g40
    +sg14
    +I3
    +sg15
    +S'N'
    +p53
    +sS'Object Name'
    +p54
    +VHeater
    +p55
    +sa(dp56
    +g6
    +g51
    +sg8
    +g9
    +sg52
    +I1
    +sg12
    +g40
    +sg14
    +I3
    +sg15
    +g53
    +sg54
    +VCooler
    +p57
    +sasS'AI_Obj'
    +p58
    +(lp59
    +(dp60
    +g6
    +S'ID0_0'
    +p61
    +sg8
    +VCurrent termperature in Beremiz lab
    +p62
    +sS'Unit ID'
    +p63
    +I62
    +sS'Object Identifier'
    +p64
    +I0
    +sg12
    +g13
    +sg14
    +I0
    +sg15
    +g53
    +sS'Engineering Units'
    +p65
    +V(Temperature) degrees-celsius (62)
    +p66
    +sS'Object Name'
    +p67
    +VTemperature
    +p68
    +sa(dp69
    +g6
    +g61
    +sg8
    +VCurrent humidity in Beremiz lab
    +p70
    +sg63
    +I29
    +sg64
    +I1
    +sg12
    +g13
    +sg14
    +I0
    +sg15
    +g53
    +sg67
    +VHumidity
    +p71
    +sg65
    +V(Humidity) percent-relative-humidity (29)
    +p72
    +sasS'MSV_Obj'
    +p73
    +(lp74
    +s.
    \ No newline at end of file
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/BACnet/bacnet_0@bacnet/baseconfnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="0" Name="bacnet_0"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/BACnet/bacnet_0@bacnet/confnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<BACnetServerNode xmlns:xsd="http://www.w3.org/2001/XMLSchema" UDP_Port_Number="47808" BACnet_Device_ID="3" BACnet_Communication_Control_Password=" " BACnet_Device_Location="Beremiz lab" Network_Interface="virbr0"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/BACnet/beremiz.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,4 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<BeremizRoot xmlns:xsd="http://www.w3.org/2001/XMLSchema" URI_location="LOCAL://">
    + <TargetType/>
    +</BeremizRoot>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/BACnet/plc.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,601 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<project xmlns:ns1="http://www.plcopen.org/xml/tc6_0201" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.plcopen.org/xml/tc6_0201">
    + <fileHeader companyName="Unknown" productName="Unnamed" productVersion="1" creationDateTime="2018-07-28T02:24:08"/>
    + <contentHeader name="BACnet" modificationDateTime="2018-07-29T01:54:59">
    + <coordinateInfo>
    + <fbd>
    + <scaling x="0" y="0"/>
    + </fbd>
    + <ld>
    + <scaling x="0" y="0"/>
    + </ld>
    + <sfc>
    + <scaling x="0" y="0"/>
    + </sfc>
    + </coordinateInfo>
    + </contentHeader>
    + <types>
    + <dataTypes/>
    + <pous>
    + <pou name="program0" pouType="program">
    + <interface>
    + <localVars>
    + <variable name="EnergyCounter" address="%MD0.2.0">
    + <type>
    + <REAL/>
    + </type>
    + </variable>
    + <variable name="Temperature" address="%ID0.0.0">
    + <type>
    + <REAL/>
    + </type>
    + </variable>
    + <variable name="Humidity" address="%ID0.0.1">
    + <type>
    + <REAL/>
    + </type>
    + </variable>
    + </localVars>
    + <localVars>
    + <variable name="TempSimulation">
    + <type>
    + <derived name="Simulator"/>
    + </type>
    + </variable>
    + <variable name="HumiditySimulation">
    + <type>
    + <derived name="Simulator"/>
    + </type>
    + </variable>
    + </localVars>
    + <localVars>
    + <variable name="TemperatureSetPoint" address="%QD0.1.0">
    + <type>
    + <REAL/>
    + </type>
    + </variable>
    + <variable name="ControlDisable" address="%QX0.4.2">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="Heater" address="%IX0.3.0">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="Cooler" address="%IX0.3.1">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + </localVars>
    + </interface>
    + <body>
    + <FBD>
    + <inVariable localId="1" executionOrderId="0" height="30" width="105" negated="false">
    + <position x="299" y="521"/>
    + <connectionPointOut>
    + <relPosition x="105" y="15"/>
    + </connectionPointOut>
    + <expression>EnergyCounter</expression>
    + </inVariable>
    + <outVariable localId="2" executionOrderId="0" height="30" width="105" negated="false">
    + <position x="654" y="521"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="3" formalParameter="OUT">
    + <position x="654" y="536"/>
    + <position x="533" y="536"/>
    + </connection>
    + </connectionPointIn>
    + <expression>EnergyCounter</expression>
    + </outVariable>
    + <block localId="3" typeName="ADD" executionOrderId="0" height="60" width="67">
    + <position x="466" y="506"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="1">
    + <position x="466" y="536"/>
    + <position x="404" y="536"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="50"/>
    + <connection refLocalId="4">
    + <position x="466" y="556"/>
    + <position x="436" y="556"/>
    + <position x="436" y="585"/>
    + <position x="401" y="585"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="67" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="4" executionOrderId="0" height="30" width="105" negated="false">
    + <position x="296" y="570"/>
    + <connectionPointOut>
    + <relPosition x="105" y="15"/>
    + </connectionPointOut>
    + <expression>0.00131</expression>
    + </inVariable>
    + <comment localId="5" height="67" width="229">
    + <position x="27" y="525"/>
    + <content>
    + <xhtml:p><![CDATA[Always consume some energy]]></xhtml:p>
    + </content>
    + </comment>
    + <block localId="6" typeName="Simulator" instanceName="TempSimulation" executionOrderId="0" height="115" width="134">
    + <position x="188" y="661"/>
    + <inputVariables>
    + <variable formalParameter="MinVal">
    + <connectionPointIn>
    + <relPosition x="0" y="35"/>
    + <connection refLocalId="8">
    + <position x="188" y="696"/>
    + <position x="138" y="696"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="MaxVal">
    + <connectionPointIn>
    + <relPosition x="0" y="66"/>
    + <connection refLocalId="9">
    + <position x="188" y="727"/>
    + <position x="138" y="727"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="PeriodSeconds">
    + <connectionPointIn>
    + <relPosition x="0" y="97"/>
    + <connection refLocalId="10">
    + <position x="188" y="758"/>
    + <position x="138" y="758"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="Out">
    + <connectionPointOut>
    + <relPosition x="134" y="35"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <outVariable localId="7" executionOrderId="0" height="30" width="92" negated="false">
    + <position x="421" y="681"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="6" formalParameter="Out">
    + <position x="421" y="696"/>
    + <position x="322" y="696"/>
    + </connection>
    + </connectionPointIn>
    + <expression>Temperature</expression>
    + </outVariable>
    + <inVariable localId="8" executionOrderId="0" height="30" width="105" negated="false">
    + <position x="33" y="681"/>
    + <connectionPointOut>
    + <relPosition x="105" y="15"/>
    + </connectionPointOut>
    + <expression>18.0</expression>
    + </inVariable>
    + <inVariable localId="9" executionOrderId="0" height="30" width="105" negated="false">
    + <position x="33" y="712"/>
    + <connectionPointOut>
    + <relPosition x="105" y="15"/>
    + </connectionPointOut>
    + <expression>30.0</expression>
    + </inVariable>
    + <inVariable localId="10" executionOrderId="0" height="30" width="105" negated="false">
    + <position x="33" y="743"/>
    + <connectionPointOut>
    + <relPosition x="105" y="15"/>
    + </connectionPointOut>
    + <expression>120</expression>
    + </inVariable>
    + <block localId="11" typeName="Simulator" instanceName="HumiditySimulation" executionOrderId="0" height="115" width="134">
    + <position x="185" y="803"/>
    + <inputVariables>
    + <variable formalParameter="MinVal">
    + <connectionPointIn>
    + <relPosition x="0" y="35"/>
    + <connection refLocalId="13">
    + <position x="185" y="838"/>
    + <position x="135" y="838"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="MaxVal">
    + <connectionPointIn>
    + <relPosition x="0" y="66"/>
    + <connection refLocalId="14">
    + <position x="185" y="869"/>
    + <position x="135" y="869"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="PeriodSeconds">
    + <connectionPointIn>
    + <relPosition x="0" y="97"/>
    + <connection refLocalId="15">
    + <position x="185" y="900"/>
    + <position x="135" y="900"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="Out">
    + <connectionPointOut>
    + <relPosition x="134" y="35"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <outVariable localId="12" executionOrderId="0" height="30" width="92" negated="false">
    + <position x="418" y="823"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="11" formalParameter="Out">
    + <position x="418" y="838"/>
    + <position x="319" y="838"/>
    + </connection>
    + </connectionPointIn>
    + <expression>Humidity</expression>
    + </outVariable>
    + <inVariable localId="13" executionOrderId="0" height="30" width="105" negated="false">
    + <position x="30" y="823"/>
    + <connectionPointOut>
    + <relPosition x="105" y="15"/>
    + </connectionPointOut>
    + <expression>55.0</expression>
    + </inVariable>
    + <inVariable localId="14" executionOrderId="0" height="30" width="105" negated="false">
    + <position x="30" y="854"/>
    + <connectionPointOut>
    + <relPosition x="105" y="15"/>
    + </connectionPointOut>
    + <expression>78.0</expression>
    + </inVariable>
    + <inVariable localId="15" executionOrderId="0" height="30" width="105" negated="false">
    + <position x="30" y="885"/>
    + <connectionPointOut>
    + <relPosition x="105" y="15"/>
    + </connectionPointOut>
    + <expression>58</expression>
    + </inVariable>
    + <block localId="16" typeName="GT" executionOrderId="0" height="60" width="67">
    + <position x="231" y="1103"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="18">
    + <position x="231" y="1133"/>
    + <position x="132" y="1133"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="50"/>
    + <connection refLocalId="22">
    + <position x="231" y="1153"/>
    + <position x="208" y="1153"/>
    + <position x="208" y="1169"/>
    + <position x="185" y="1169"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="67" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="18" executionOrderId="0" height="30" width="92" negated="false">
    + <position x="40" y="1118"/>
    + <connectionPointOut>
    + <relPosition x="92" y="15"/>
    + </connectionPointOut>
    + <expression>Temperature</expression>
    + </inVariable>
    + <block localId="19" typeName="AND" executionOrderId="0" height="60" width="67">
    + <position x="347" y="1059"/>
    + <inputVariables>
    + <variable formalParameter="IN1" negated="true">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="20">
    + <position x="347" y="1089"/>
    + <position x="263" y="1089"/>
    + <position x="263" y="1074"/>
    + <position x="145" y="1074"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="50"/>
    + <connection refLocalId="16" formalParameter="OUT">
    + <position x="347" y="1109"/>
    + <position x="337" y="1109"/>
    + <position x="337" y="1133"/>
    + <position x="298" y="1133"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="67" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="20" executionOrderId="0" height="30" width="104" negated="false">
    + <position x="41" y="1059"/>
    + <connectionPointOut>
    + <relPosition x="104" y="15"/>
    + </connectionPointOut>
    + <expression>ControlDisable</expression>
    + </inVariable>
    + <outVariable localId="21" executionOrderId="0" height="30" width="92" negated="false">
    + <position x="468" y="1074"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="19" formalParameter="OUT">
    + <position x="468" y="1089"/>
    + <position x="414" y="1089"/>
    + </connection>
    + </connectionPointIn>
    + <expression>Cooler</expression>
    + </outVariable>
    + <inVariable localId="22" executionOrderId="0" height="30" width="146" negated="false">
    + <position x="39" y="1154"/>
    + <connectionPointOut>
    + <relPosition x="146" y="15"/>
    + </connectionPointOut>
    + <expression>TemperatureSetPoint</expression>
    + </inVariable>
    + <block localId="17" typeName="LT" executionOrderId="0" height="60" width="67">
    + <position x="228" y="1278"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="23">
    + <position x="228" y="1308"/>
    + <position x="129" y="1308"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="50"/>
    + <connection refLocalId="27">
    + <position x="228" y="1328"/>
    + <position x="205" y="1328"/>
    + <position x="205" y="1344"/>
    + <position x="182" y="1344"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="67" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="23" executionOrderId="0" height="30" width="92" negated="false">
    + <position x="37" y="1293"/>
    + <connectionPointOut>
    + <relPosition x="92" y="15"/>
    + </connectionPointOut>
    + <expression>Temperature</expression>
    + </inVariable>
    + <block localId="24" typeName="AND" executionOrderId="0" height="60" width="67">
    + <position x="344" y="1234"/>
    + <inputVariables>
    + <variable formalParameter="IN1" negated="true">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="25">
    + <position x="344" y="1264"/>
    + <position x="260" y="1264"/>
    + <position x="260" y="1249"/>
    + <position x="142" y="1249"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="50"/>
    + <connection refLocalId="17" formalParameter="OUT">
    + <position x="344" y="1284"/>
    + <position x="334" y="1284"/>
    + <position x="334" y="1308"/>
    + <position x="295" y="1308"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="67" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="25" executionOrderId="0" height="30" width="104" negated="false">
    + <position x="38" y="1234"/>
    + <connectionPointOut>
    + <relPosition x="104" y="15"/>
    + </connectionPointOut>
    + <expression>ControlDisable</expression>
    + </inVariable>
    + <outVariable localId="26" executionOrderId="0" height="30" width="92" negated="false">
    + <position x="465" y="1249"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="24" formalParameter="OUT">
    + <position x="465" y="1264"/>
    + <position x="411" y="1264"/>
    + </connection>
    + </connectionPointIn>
    + <expression>Heater</expression>
    + </outVariable>
    + <inVariable localId="27" executionOrderId="0" height="30" width="146" negated="false">
    + <position x="36" y="1329"/>
    + <connectionPointOut>
    + <relPosition x="146" y="15"/>
    + </connectionPointOut>
    + <expression>TemperatureSetPoint</expression>
    + </inVariable>
    + <comment localId="28" height="67" width="229">
    + <position x="343" y="734"/>
    + <content>
    + <xhtml:p><![CDATA[Simple sensor simulation]]></xhtml:p>
    + </content>
    + </comment>
    + <comment localId="29" height="67" width="229">
    + <position x="37" y="978"/>
    + <content>
    + <xhtml:p><![CDATA[Climate control]]></xhtml:p>
    + </content>
    + </comment>
    + <comment localId="30" height="464" width="773">
    + <position x="14" y="16"/>
    + <content>
    + <xhtml:p><![CDATA[This examples shows how to work with BACnet extension.
    +
    +Extensions requires native BACnet stack to be installed nearby Beremiz.
    +Following directory structure is expected:
    +<Parent directory>
    + "beremiz"
    + "BACnet"
    +
    +If library is installed elsewhere, then place corresponding paths
    +in CFLAGS/LDFLAGS in project settings.
    +
    +For GNU/Linux to install BACnet library in parent directory run following commands:
    +$ svn checkout https://svn.code.sf.net/p/bacnet/code/trunk/bacnet-stack/ BACnet
    +$ cd BACnet
    +$ make
    +
    +After that BACnet extension is ready to be used in Beremiz projects.
    +BACnet stack implementation contains a lot of test tools. They could be useful during
    +debugging and BACnet investigation. See "BACnet/bin/readme.txt" for more information about them.]]></xhtml:p>
    + </content>
    + </comment>
    + </FBD>
    + </body>
    + </pou>
    + <pou name="Simulator" pouType="functionBlock">
    + <interface>
    + <outputVars>
    + <variable name="Out">
    + <type>
    + <REAL/>
    + </type>
    + </variable>
    + </outputVars>
    + <inputVars>
    + <variable name="MinVal">
    + <type>
    + <REAL/>
    + </type>
    + </variable>
    + <variable name="MaxVal">
    + <type>
    + <REAL/>
    + </type>
    + </variable>
    + <variable name="PeriodSeconds">
    + <type>
    + <INT/>
    + </type>
    + </variable>
    + </inputVars>
    + <localVars>
    + <variable name="TON0">
    + <type>
    + <derived name="TON"/>
    + </type>
    + </variable>
    + <variable name="seconds">
    + <type>
    + <INT/>
    + </type>
    + </variable>
    + <variable name="BaseVal">
    + <type>
    + <REAL/>
    + </type>
    + </variable>
    + <variable name="VarVal">
    + <type>
    + <REAL/>
    + </type>
    + </variable>
    + </localVars>
    + </interface>
    + <body>
    + <ST>
    + <xhtml:p><![CDATA[(* pseudo-random variations *)
    +TON0(IN := TRUE, PT := T#3120s);
    +IF TON0.Q THEN
    + TON0(IN := FALSE);
    +END_IF;
    +seconds := TIME_TO_INT(TON0.ET);
    +
    +BaseVal := (MaxVal + MinVal)/2.0;
    +VarVal := (MaxVal-MinVal)*INT_TO_REAL((seconds MOD PeriodSeconds) - (PeriodSeconds/2))/INT_TO_REAL(PeriodSeconds);
    +
    +Out := BaseVal + VarVal;]]></xhtml:p>
    + </ST>
    + </body>
    + </pou>
    + </pous>
    + </types>
    + <instances>
    + <configurations>
    + <configuration name="config">
    + <resource name="resource1">
    + <task name="task0" priority="0" interval="T#20ms">
    + <pouInstance name="instance0" typeName="program0"/>
    + </task>
    + </resource>
    + </configuration>
    + </configurations>
    + </instances>
    +</project>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/beremiz.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,6 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<BeremizRoot xmlns:xsd="http://www.w3.org/2001/XMLSchema" URI_location="LOCAL://">
    + <TargetType>
    + <Linux/>
    + </TargetType>
    +</BeremizRoot>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/ModbusRequest_0@ModbusRequest/baseconfnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="0" Name="ModbusRequest_0"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/ModbusRequest_0@ModbusRequest/confnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<ModbusRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema" Function="16 - Write Multiple Registers" SlaveID="0"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/ModbusRequest_1@ModbusRequest/baseconfnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="1" Name="ModbusRequest_1"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/ModbusRequest_1@ModbusRequest/confnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<ModbusRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema" Function="04 - Read Input Registers" SlaveID="0" Start_Address="0"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/baseconfnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="0" Name="ModbusTCPclient_0"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPclient_0@ModbusTCPclient/confnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<ModbusTCPclient xmlns:xsd="http://www.w3.org/2001/XMLSchema" Remote_Port_Number="1502"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/HoldingRegs@MemoryArea/baseconfnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="0" Name="HoldingRegs"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/HoldingRegs@MemoryArea/confnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<MemoryArea xmlns:xsd="http://www.w3.org/2001/XMLSchema" MemoryAreaType="03 - Holding Registers" Nr_of_Channels="1"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/InputRegs@MemoryArea/baseconfnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="1" Name="InputRegs"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/InputRegs@MemoryArea/confnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<MemoryArea xmlns:xsd="http://www.w3.org/2001/XMLSchema" MemoryAreaType="04 - Input Registers"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/baseconfnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="1" Name="ModbusTCPserver_0"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/ModbusTCPserver_0@ModbusTCPserver/confnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<ModbusServerNode xmlns:xsd="http://www.w3.org/2001/XMLSchema" Local_Port_Number="1502" Local_IP_Address="127.0.0.1"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/baseconfnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="0" Name="modbus_0"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/modbus_0@modbus/confnode.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,2 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<ModbusRoot xmlns:xsd="http://www.w3.org/2001/XMLSchema"/>
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/tests/modbus/plc.xml Wed Aug 08 13:46:19 2018 +0200
    @@ -0,0 +1,314 @@
    +<?xml version='1.0' encoding='utf-8'?>
    +<project xmlns:ns1="http://www.plcopen.org/xml/tc6_0201" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.plcopen.org/xml/tc6_0201">
    + <fileHeader companyName="Beremiz" productName="Beremiz" productVersion="1" creationDateTime="2018-07-27T13:19:12"/>
    + <contentHeader name="Modbus" modificationDateTime="2018-07-27T15:43:56">
    + <coordinateInfo>
    + <fbd>
    + <scaling x="0" y="0"/>
    + </fbd>
    + <ld>
    + <scaling x="0" y="0"/>
    + </ld>
    + <sfc>
    + <scaling x="0" y="0"/>
    + </sfc>
    + </coordinateInfo>
    + </contentHeader>
    + <types>
    + <dataTypes/>
    + <pous>
    + <pou name="program0" pouType="program">
    + <interface>
    + <localVars>
    + <variable name="Counter">
    + <type>
    + <INT/>
    + </type>
    + </variable>
    + <variable name="CounterReadBack">
    + <type>
    + <INT/>
    + </type>
    + </variable>
    + </localVars>
    + <localVars>
    + <variable name="MasterWriteToReg0" address="%QW0.0.0.0">
    + <type>
    + <INT/>
    + </type>
    + </variable>
    + <variable name="MasterReadFromReg1" address="%IW0.0.1.0">
    + <type>
    + <INT/>
    + </type>
    + </variable>
    + <variable name="SlaveHoldReg0" address="%IW0.1.0.0">
    + <type>
    + <WORD/>
    + </type>
    + </variable>
    + <variable name="SlaveInputReg0" address="%QW0.1.1.0">
    + <type>
    + <WORD/>
    + </type>
    + </variable>
    + </localVars>
    + <localVars>
    + <variable name="CTU0">
    + <type>
    + <derived name="CTU"/>
    + </type>
    + </variable>
    + <variable name="Generator0">
    + <type>
    + <derived name="Generator"/>
    + </type>
    + </variable>
    + </localVars>
    + </interface>
    + <body>
    + <FBD>
    + <comment localId="4" height="109" width="350">
    + <position x="102" y="438"/>
    + <content>
    + <xhtml:p><![CDATA[Modbus TCP Master writes counter value to one holding register on Modbus TCP Slave and reads it back from other input register.]]></xhtml:p>
    + </content>
    + </comment>
    + <comment localId="3" height="407" width="680">
    + <position x="21" y="15"/>
    + <content>
    + <xhtml:p><![CDATA[This examples shows how to work with Modbus extension. It uses Modbus TCP, but the same functions are available for Modbus RTU as well. Buth protocols are supported.
    +
    +Modbus extensions requires native Modbus RTU/TCP library to be installed nearby Beremiz.
    +Following directory structure is expected:
    +<Parent directory>
    + "beremiz"
    + "Modbus"
    +
    +If Modbus library is installed elsewhere, then place corresponding paths
    +in CFLAGS/LDFLAGS in project settings.
    +
    +For GNU/Linux to install Modbus library in parent directory run following commands:
    +$ hg clone https://bitbucket.org/mjsousa/modbus Modbus
    +$ cd Modbus
    +$ make
    +
    +After that Modbus extension is ready to be used in Beremiz projects.]]></xhtml:p>
    + </content>
    + </comment>
    + <block localId="5" typeName="CTU" instanceName="CTU0" executionOrderId="0" height="80" width="52">
    + <position x="346" y="605"/>
    + <inputVariables>
    + <variable formalParameter="CU" edge="rising">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="6" formalParameter="OUT">
    + <position x="346" y="635"/>
    + <position x="303" y="635"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="R">
    + <connectionPointIn>
    + <relPosition x="0" y="50"/>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="PV">
    + <connectionPointIn>
    + <relPosition x="0" y="70"/>
    + <connection refLocalId="7">
    + <position x="346" y="675"/>
    + <position x="324" y="675"/>
    + <position x="324" y="703"/>
    + <position x="302" y="703"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="Q">
    + <connectionPointOut>
    + <relPosition x="52" y="30"/>
    + </connectionPointOut>
    + </variable>
    + <variable formalParameter="CV">
    + <connectionPointOut>
    + <relPosition x="52" y="50"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <block localId="6" typeName="Generator" instanceName="Generator0" executionOrderId="0" height="60" width="79">
    + <position x="224" y="605"/>
    + <inputVariables>
    + <variable formalParameter="PON">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="1">
    + <position x="224" y="635"/>
    + <position x="154" y="635"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="POFF">
    + <connectionPointIn>
    + <relPosition x="0" y="50"/>
    + <connection refLocalId="1">
    + <position x="224" y="655"/>
    + <position x="189" y="655"/>
    + <position x="189" y="635"/>
    + <position x="154" y="635"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="79" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="1" executionOrderId="0" height="30" width="138" negated="false">
    + <position x="16" y="620"/>
    + <connectionPointOut>
    + <relPosition x="138" y="15"/>
    + </connectionPointOut>
    + <expression>T#1s</expression>
    + </inVariable>
    + <inVariable localId="7" executionOrderId="0" height="30" width="138" negated="false">
    + <position x="164" y="688"/>
    + <connectionPointOut>
    + <relPosition x="138" y="15"/>
    + </connectionPointOut>
    + <expression>32767</expression>
    + </inVariable>
    + <inOutVariable localId="2" executionOrderId="0" height="30" width="138" negatedOut="false" negatedIn="false">
    + <position x="544" y="640"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="5" formalParameter="CV">
    + <position x="544" y="655"/>
    + <position x="398" y="655"/>
    + </connection>
    + </connectionPointIn>
    + <connectionPointOut>
    + <relPosition x="138" y="15"/>
    + </connectionPointOut>
    + <expression>Counter</expression>
    + </inOutVariable>
    + <outVariable localId="8" executionOrderId="0" height="30" width="138" negated="false">
    + <position x="762" y="640"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="2">
    + <position x="762" y="655"/>
    + <position x="682" y="655"/>
    + </connection>
    + </connectionPointIn>
    + <expression>MasterWriteToReg0</expression>
    + </outVariable>
    + <inVariable localId="9" executionOrderId="0" height="30" width="152" negated="false">
    + <position x="81" y="747"/>
    + <connectionPointOut>
    + <relPosition x="152" y="15"/>
    + </connectionPointOut>
    + <expression>MasterReadFromReg1</expression>
    + </inVariable>
    + <outVariable localId="10" executionOrderId="0" height="30" width="137" negated="false">
    + <position x="547" y="747"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="9">
    + <position x="547" y="762"/>
    + <position x="233" y="762"/>
    + </connection>
    + </connectionPointIn>
    + <expression>CounterReadBack</expression>
    + </outVariable>
    + <comment localId="11" height="109" width="350">
    + <position x="85" y="825"/>
    + <content>
    + <xhtml:p><![CDATA[Modbus TCP Slave just copies received register value from holding register to input register.]]></xhtml:p>
    + </content>
    + </comment>
    + <inVariable localId="12" executionOrderId="0" height="30" width="152" negated="false">
    + <position x="82" y="970"/>
    + <connectionPointOut>
    + <relPosition x="152" y="15"/>
    + </connectionPointOut>
    + <expression>SlaveHoldReg0</expression>
    + </inVariable>
    + <outVariable localId="13" executionOrderId="0" height="30" width="123" negated="false">
    + <position x="548" y="970"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="12">
    + <position x="548" y="985"/>
    + <position x="234" y="985"/>
    + </connection>
    + </connectionPointIn>
    + <expression>SlaveInputReg0</expression>
    + </outVariable>
    + </FBD>
    + </body>
    + </pou>
    + <pou name="Generator" pouType="functionBlock">
    + <interface>
    + <outputVars>
    + <variable name="OUT">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + </outputVars>
    + <inputVars>
    + <variable name="PON">
    + <type>
    + <TIME/>
    + </type>
    + </variable>
    + <variable name="POFF">
    + <type>
    + <TIME/>
    + </type>
    + </variable>
    + </inputVars>
    + <localVars>
    + <variable name="T1">
    + <type>
    + <derived name="TON"/>
    + </type>
    + </variable>
    + <variable name="T2">
    + <type>
    + <derived name="TOF"/>
    + </type>
    + </variable>
    + </localVars>
    + </interface>
    + <body>
    + <ST>
    + <xhtml:p><![CDATA[T1( IN := NOT T2.Q, PT := POFF);
    +T2( IN := T1.Q, PT := PON);
    +OUT := T2.Q;]]></xhtml:p>
    + </ST>
    + </body>
    + </pou>
    + </pous>
    + </types>
    + <instances>
    + <configurations>
    + <configuration name="config">
    + <resource name="resource1">
    + <task name="task0" priority="0" interval="T#20ms">
    + <pouInstance name="instance0" typeName="program0"/>
    + </task>
    + </resource>
    + </configuration>
    + </configurations>
    + </instances>
    +</project>