--- a/CodeFileTreeNode.py Tue Feb 17 10:23:57 2015 +0100
+++ b/CodeFileTreeNode.py Thu Feb 19 00:40:53 2015 +0100
@@ -31,6 +31,9 @@
<xsd:attribute name="initial" type="xsd:string" use="optional" default=""/>
+ <xsd:attribute name="desc" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="onchange" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="opts" type="xsd:string" use="optional" default=""/> @@ -119,6 +122,9 @@
variable.setname(var["Name"])
variable.settype(var["Type"])
variable.setinitial(var["Initial"])
+ variable.setdesc(var["Description"]) + variable.setonchange(var["OnChange"]) + variable.setopts(var["Options"]) self.CodeFile.variables.appendvariable(variable)
@@ -126,7 +132,11 @@
for var in self.CodeFileVariables(self.CodeFile):
datas.append({"Name" : var.getname(),
- "Initial" : var.getinitial()})
+ "Initial" : var.getinitial(), + "Description" : var.getdesc(), + "OnChange" : var.getonchange(), + "Options" : var.getopts(), def SetTextParts(self, parts):
@@ -157,11 +167,15 @@
def CTNGlobalInstances(self):
- current_location = self.GetCurrentLocation()
- return [(variable.getname(),
+ variables = self.CodeFileVariables(self.CodeFile) + ret = [(variable.getname(),
- for variable in self.CodeFileVariables(self.CodeFile)]
+ for variable in variables] + ret.extend([("On"+variable.getname()+"Change", "python_poll", "") + for variable in variables + if variable.getonchange()]) #-------------------------------------------------------------------------------
# Current Buffering Management Functions
--- a/ProjectController.py Tue Feb 17 10:23:57 2015 +0100
+++ b/ProjectController.py Thu Feb 19 00:40:53 2015 +0100
@@ -982,7 +982,7 @@
- self.LocationCFilesAndCFLAGS = CTNLocationCFilesAndCFLAGS + LibCFilesAndCFLAGS
+ self.LocationCFilesAndCFLAGS = LibCFilesAndCFLAGS + CTNLocationCFilesAndCFLAGS self.LDFLAGS = CTNLDFLAGS + LibLDFLAGS
ExtraFiles = CTNExtraFiles + LibExtraFiles
--- a/editors/CodeFileEditor.py Tue Feb 17 10:23:57 2015 +0100
+++ b/editors/CodeFileEditor.py Thu Feb 19 00:40:53 2015 +0100
@@ -607,7 +607,7 @@
colname = self.GetColLabelValue(col, False)
- if colname in ["Name", "Initial"]:
+ if colname in ["Name", "Initial", "Description", "OnChange", "Options"]: editor = wx.grid.GridCellTextEditor()
editor = wx.grid.GridCellChoiceEditor()
@@ -658,10 +658,13 @@
self.ParentWindow = window
self.Controler = controler
- self.VariablesDefaultValue = {"Name" : "", "Type" : DefaultType, "Initial": ""}
- self.Table = VariablesTable(self, [], ["#", "Name", "Type", "Initial"])
- self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
- self.ColSizes = [40, 200, 150, 150]
+ self.VariablesDefaultValue = {"Name" : "", "Type" : DefaultType, "Initial": "", + "Description":"", "OnChange":"", "Options":""} + self.Table = VariablesTable(self, [], ["#", "Name", "Type", "Initial", + "Description", "OnChange", "Options"]) + self.ColAlignements = [wx.ALIGN_RIGHT] + \ + [wx.ALIGN_LEFT]*(len(self.VariablesDefaultValue)) + self.ColSizes = [20, 150] + [100]*(len(self.VariablesDefaultValue)-1) self.VariablesGrid.SetTable(self.Table)
self.VariablesGrid.SetButtons({"Add": self.AddVariableButton,
"Delete": self.DeleteVariableButton,
--- a/py_ext/PythonFileCTNMixin.py Tue Feb 17 10:23:57 2015 +0100
+++ b/py_ext/PythonFileCTNMixin.py Thu Feb 19 00:40:53 2015 +0100
@@ -65,7 +65,6 @@
getattr(self.CodeFile, section).getanyText() + "\n" + \
self.PostSectionsTexts.get(section,"")
def CTNGenerate_C(self, buildpath, locations):
# location string for that CTN
location_str = "_".join(map(lambda x:str(x),
@@ -73,7 +72,17 @@
configname = self.GetCTRoot().GetProjectConfigNames()[0]
pyextname = self.CTNName()
+ varinfos = map(lambda variable : { + "name": variable.getname(), + "desc" : repr(variable.getdesc()), + "onchange" : '"'+variable.getonchange()+"('"+variable.getname()+"')\"" \ + if variable.getonchange() else "", + "opts" : repr(variable.getopts()), + "configname" : configname.upper(), + "uppername" : variable.getname().upper(), + "IECtype" : variable.gettype(), + "pyextname" :pyextname}, + self.CodeFile.variables.variable) # python side PLC global variables access stub
globalstubs = "\n".join(["""\
_%(name)s_ctype, _%(name)s_unpack, _%(name)s_pack = \\
@@ -84,13 +93,12 @@
_PySafeSetPLCGlob_%(name)s = PLCBinary.__SafeSetPLCGlob_%(name)s
_PySafeSetPLCGlob_%(name)s.restype = None
_PySafeSetPLCGlob_%(name)s.argtypes = [ctypes.POINTER(_%(name)s_ctype)]
-_%(pyextname)sGlobalsDesc.append(("%(name)s","%(IECtype)s"))
-""" % { "name": variable.getname(),
- "configname": configname.upper(),
- "uppername": variable.getname().upper(),
- "IECtype": variable.gettype(),
- for variable in self.CodeFile.variables.variable])
+_%(pyextname)sGlobalsDesc.append(( +""" % varinfo for varinfo in varinfos]) # Runtime calls (start, stop, init, and cleanup)
@@ -156,6 +164,11 @@
+ vardeconchangefmt = """\ +PYTHON_POLL* __%(name)s_notifier; if(!AtomicCompareExchange(&__%(name)s_wlock, 0, 1)){
if(__%(name)s_wbuffer_written == 1){
@@ -167,24 +180,36 @@
if(!AtomicCompareExchange(&__%(name)s_rlock, 0, 1)){
- __%(name)s_rbuffer = %(configname)s__%(uppername)s.value;
+ __%(name)s_rbuffer = __GET_VAR(%(configname)s__%(uppername)s); AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
- var_str = map("\n".join, zip(*[
- map(lambda f : f % varinfo,
- (vardecfmt, varretfmt, varpubfmt))
- for varinfo in map(lambda variable : {
- "name": variable.getname(),
- "configname": configname.upper(),
- "uppername": variable.getname().upper(),
- "IECtype": variable.gettype()},
- self.CodeFile.variables.variable)]))
- vardec, varret, varpub = var_str
- vardec = varret = varpub = ""
+ varpubonchangefmt = """\ + if(!AtomicCompareExchange(&__%(name)s_rlock, 0, 1)){ + IEC_%(IECtype)s tmp = __GET_VAR(%(configname)s__%(uppername)s); + if(__%(name)s_rbuffer != tmp){ + __%(name)s_rbuffer = %(configname)s__%(uppername)s.value; + PYTHON_POLL_body__(__%(name)s_notifier); + AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0); + varinitonchangefmt = """\ + __%(name)s_notifier = __GET_GLOBAL_ON%(uppername)sCHANGE(); + __SET_VAR(__%(name)s_notifier->,TRIG,,__BOOL_LITERAL(TRUE)); + __SET_VAR(__%(name)s_notifier->,CODE,,__STRING_LITERAL(%(onchangelen)d,%(onchange)s)); + vardec = "\n".join([(vardecfmt + vardeconchangefmt + if varinfo["onchange"] else vardecfmt)% varinfo + for varinfo in varinfos]) + varret = "\n".join([varretfmt % varinfo for varinfo in varinfos]) + varpub = "\n".join([(varpubonchangefmt if varinfo["onchange"] else + for varinfo in varinfos]) + varinit = "\n".join([varinitonchangefmt % dict( + onchangelen = len(varinfo["onchange"]),**varinfo) + for varinfo in varinfos if varinfo["onchange"]]) @@ -192,6 +217,8 @@
* for safe global variables access
#include "iec_types_all.h"
/* User variables reference */
@@ -199,6 +226,7 @@
/* Beremiz confnode functions */
int __init_%(location_str)s(int argc,char **argv){
--- a/tests/wamp/beremiz.xml Tue Feb 17 10:23:57 2015 +0100
+++ b/tests/wamp/beremiz.xml Thu Feb 19 00:40:53 2015 +0100
@@ -1,4 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
-<BeremizRoot xmlns:xsd="http://www.w3.org/2001/XMLSchema" URI_location="WAMP://127.0.0.1:8888#Automation#wamptest">
+<BeremizRoot xmlns:xsd="http://www.w3.org/2001/XMLSchema" URI_location="WAMP://127.0.0.1:8888#Automation#2534667845"> --- a/tests/wamp/plc.xml Tue Feb 17 10:23:57 2015 +0100
+++ b/tests/wamp/plc.xml Thu Feb 19 00:40:53 2015 +0100
@@ -1,7 +1,7 @@
<?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="2015-02-05T11:44:55" contentDescription=" "/>
- <contentHeader name="WAMPTest" modificationDateTime="2015-02-07T22:25:01">
+ <contentHeader name="WAMPTest" modificationDateTime="2015-02-18T23:59:50">