99 self.iec2c_buildopts = None |
99 self.iec2c_buildopts = None |
100 self.ieclib_path = self.findLibPath() |
100 self.ieclib_path = self.findLibPath() |
101 self.ieclib_c_path = self.findLibCPath() |
101 self.ieclib_c_path = self.findLibCPath() |
102 |
102 |
103 def findObject(self, paths, test): |
103 def findObject(self, paths, test): |
104 path=None |
104 path = None |
105 for p in paths: |
105 for p in paths: |
106 if test(p): |
106 if test(p): |
107 path = p |
107 path = p |
108 break |
108 break |
109 return path |
109 return path |
110 |
110 |
111 def findCmd(self): |
111 def findCmd(self): |
112 cmd="iec2c"+(".exe" if wx.Platform == '__WXMSW__' else "") |
112 cmd = "iec2c"+(".exe" if wx.Platform == '__WXMSW__' else "") |
113 paths=[ |
113 paths = [ |
114 os.path.join(base_folder, "matiec") |
114 os.path.join(base_folder, "matiec") |
115 ] |
115 ] |
116 path = self.findObject(paths, lambda p: os.path.isfile(os.path.join(p, cmd))) |
116 path = self.findObject(paths, lambda p: os.path.isfile(os.path.join(p, cmd))) |
117 |
117 |
118 # otherwise use iec2c from PATH |
118 # otherwise use iec2c from PATH |
119 if path is not None: |
119 if path is not None: |
120 cmd=os.path.join(path, cmd) |
120 cmd = os.path.join(path, cmd) |
121 |
121 |
122 return cmd |
122 return cmd |
123 |
123 |
124 def findLibPath(self): |
124 def findLibPath(self): |
125 paths=[ |
125 paths = [ |
126 os.path.join(base_folder, "matiec", "lib"), |
126 os.path.join(base_folder, "matiec", "lib"), |
127 "/usr/lib/matiec" |
127 "/usr/lib/matiec" |
128 ] |
128 ] |
129 path = self.findObject(paths, lambda p: os.path.isfile(os.path.join(p, "ieclib.txt"))) |
129 path = self.findObject(paths, lambda p: os.path.isfile(os.path.join(p, "ieclib.txt"))) |
130 return path |
130 return path |
131 |
131 |
132 def findLibCPath(self): |
132 def findLibCPath(self): |
133 path=None |
133 path = None |
134 paths=[ |
134 paths = [ |
135 os.path.join(self.ieclib_path, "C"), |
135 os.path.join(self.ieclib_path, "C"), |
136 self.ieclib_path] |
136 self.ieclib_path] |
137 path = self.findObject(paths, lambda p: os.path.isfile(os.path.join(p, "iec_types.h"))) |
137 path = self.findObject(paths, lambda p: os.path.isfile(os.path.join(p, "iec_types.h"))) |
138 return path |
138 return path |
139 |
139 |
140 def findSupportedOptions(self): |
140 def findSupportedOptions(self): |
141 buildcmd = "\"%s\" -h" % (self.getCmd()) |
141 buildcmd = "\"%s\" -h" % (self.getCmd()) |
142 options =["-f", "-l", "-p"] |
142 options = ["-f", "-l", "-p"] |
143 |
143 |
144 buildopt = "" |
144 buildopt = "" |
145 try: |
145 try: |
146 # Invoke compiler. Output files are listed to stdout, errors to stderr |
146 # Invoke compiler. Output files are listed to stdout, errors to stderr |
147 status, result, err_result = ProcessLogger(None, buildcmd, |
147 status, result, err_result = ProcessLogger(None, buildcmd, |
202 </xsd:choice> |
202 </xsd:choice> |
203 </xsd:complexType> |
203 </xsd:complexType> |
204 </xsd:element>"""+((""" |
204 </xsd:element>"""+((""" |
205 <xsd:element name="Libraries" minOccurs="0"> |
205 <xsd:element name="Libraries" minOccurs="0"> |
206 <xsd:complexType> |
206 <xsd:complexType> |
207 """+"\n".join(['<xsd:attribute name='+ |
207 """+"\n".join(['<xsd:attribute name=' + |
208 '"Enable_'+ libname + '_Library" '+ |
208 '"Enable_' + libname + '_Library" ' + |
209 'type="xsd:boolean" use="optional" default="true"/>' |
209 'type="xsd:boolean" use="optional" default="true"/>' |
210 for libname, lib in features.libraries])+""" |
210 for libname, lib in features.libraries])+""" |
211 </xsd:complexType> |
211 </xsd:complexType> |
212 </xsd:element>""") if len(features.libraries)>0 else '') + """ |
212 </xsd:element>""") if len(features.libraries) > 0 else '') + """ |
213 </xsd:sequence> |
213 </xsd:sequence> |
214 <xsd:attribute name="URI_location" type="xsd:string" use="optional" default=""/> |
214 <xsd:attribute name="URI_location" type="xsd:string" use="optional" default=""/> |
215 <xsd:attribute name="Disable_Extensions" type="xsd:boolean" use="optional" default="false"/> |
215 <xsd:attribute name="Disable_Extensions" type="xsd:boolean" use="optional" default="false"/> |
216 </xsd:complexType> |
216 </xsd:complexType> |
217 </xsd:element> |
217 </xsd:element> |
232 |
232 |
233 # Setup debug information |
233 # Setup debug information |
234 self.IECdebug_datas = {} |
234 self.IECdebug_datas = {} |
235 self.IECdebug_lock = Lock() |
235 self.IECdebug_lock = Lock() |
236 |
236 |
237 self.DebugTimer=None |
237 self.DebugTimer = None |
238 self.ResetIECProgramsAndVariables() |
238 self.ResetIECProgramsAndVariables() |
239 |
239 |
240 # In both new or load scenario, no need to save |
240 # In both new or load scenario, no need to save |
241 self.ChangesToSave = False |
241 self.ChangesToSave = False |
242 # root have no parent |
242 # root have no parent |
259 self.DebugTimer.cancel() |
259 self.DebugTimer.cancel() |
260 self.KillDebugThread() |
260 self.KillDebugThread() |
261 |
261 |
262 def LoadLibraries(self): |
262 def LoadLibraries(self): |
263 self.Libraries = [] |
263 self.Libraries = [] |
264 TypeStack=[] |
264 TypeStack = [] |
265 for libname, clsname in features.libraries: |
265 for libname, clsname in features.libraries: |
266 if self.BeremizRoot.Libraries is None or getattr(self.BeremizRoot.Libraries, "Enable_"+libname+"_Library"): |
266 if self.BeremizRoot.Libraries is None or getattr(self.BeremizRoot.Libraries, "Enable_"+libname+"_Library"): |
267 Lib = GetClassImporter(clsname)()(self, libname, TypeStack) |
267 Lib = GetClassImporter(clsname)()(self, libname, TypeStack) |
268 TypeStack.append(Lib.GetTypes()) |
268 TypeStack.append(Lib.GetTypes()) |
269 self.Libraries.append(Lib) |
269 self.Libraries.append(Lib) |
566 |
566 |
567 def GetLibrariesSTCode(self): |
567 def GetLibrariesSTCode(self): |
568 return "\n".join([ lib.GetSTCode() for lib in self.Libraries ]) |
568 return "\n".join([ lib.GetSTCode() for lib in self.Libraries ]) |
569 |
569 |
570 def GetLibrariesCCode(self, buildpath): |
570 def GetLibrariesCCode(self, buildpath): |
571 if len(self.Libraries)==0: |
571 if len(self.Libraries) == 0: |
572 return [], [], () |
572 return [], [], () |
573 self.GetIECProgramsAndVariables() |
573 self.GetIECProgramsAndVariables() |
574 LibIECCflags = '"-I%s" -Wno-unused-function' % os.path.abspath(self.GetIECLibPath()) |
574 LibIECCflags = '"-I%s" -Wno-unused-function' % os.path.abspath(self.GetIECLibPath()) |
575 LocatedCCodeAndFlags=[] |
575 LocatedCCodeAndFlags = [] |
576 Extras=[] |
576 Extras = [] |
577 for lib in self.Libraries: |
577 for lib in self.Libraries: |
578 res=lib.Generate_C(buildpath, self._VariablesList, LibIECCflags) |
578 res = lib.Generate_C(buildpath, self._VariablesList, LibIECCflags) |
579 LocatedCCodeAndFlags.append(res[:2]) |
579 LocatedCCodeAndFlags.append(res[:2]) |
580 if len(res)>2: |
580 if len(res) > 2: |
581 Extras.extend(res[2:]) |
581 Extras.extend(res[2:]) |
582 return map(list, zip(*LocatedCCodeAndFlags))+[tuple(Extras)] |
582 return map(list, zip(*LocatedCCodeAndFlags))+[tuple(Extras)] |
583 |
583 |
584 # Update PLCOpenEditor ConfNode Block types from loaded confnodes |
584 # Update PLCOpenEditor ConfNode Block types from loaded confnodes |
585 def RefreshConfNodesBlockLists(self): |
585 def RefreshConfNodesBlockLists(self): |
786 |
786 |
787 self.logger.write_error(_("Error : IEC to C compiler returned %d\n") % status) |
787 self.logger.write_error(_("Error : IEC to C compiler returned %d\n") % status) |
788 return False |
788 return False |
789 |
789 |
790 # Now extract C files of stdout |
790 # Now extract C files of stdout |
791 C_files = [ fname for fname in result.splitlines() if fname[-2:]==".c" or fname[-2:]==".C" ] |
791 C_files = [ fname for fname in result.splitlines() if fname[-2:] == ".c" or fname[-2:] == ".C" ] |
792 # remove those that are not to be compiled because included by others |
792 # remove those that are not to be compiled because included by others |
793 C_files.remove("POUS.c") |
793 C_files.remove("POUS.c") |
794 if not C_files: |
794 if not C_files: |
795 self.logger.write_error(_("Error : At least one configuration and one resource must be declared in PLC !\n")) |
795 self.logger.write_error(_("Error : At least one configuration and one resource must be declared in PLC !\n")) |
796 return False |
796 return False |
797 # transform those base names to full names with path |
797 # transform those base names to full names with path |
798 C_files = map(lambda filename: os.path.join(buildpath, filename), C_files) |
798 C_files = map(lambda filename: os.path.join(buildpath, filename), C_files) |
799 |
799 |
800 # prepend beremiz include to configuration header |
800 # prepend beremiz include to configuration header |
801 H_files = [ fname for fname in result.splitlines() if fname[-2:]==".h" or fname[-2:]==".H" ] |
801 H_files = [ fname for fname in result.splitlines() if fname[-2:] == ".h" or fname[-2:] == ".H" ] |
802 H_files.remove("LOCATED_VARIABLES.h") |
802 H_files.remove("LOCATED_VARIABLES.h") |
803 H_files = map(lambda filename: os.path.join(buildpath, filename), H_files) |
803 H_files = map(lambda filename: os.path.join(buildpath, filename), H_files) |
804 for H_file in H_files: |
804 for H_file in H_files: |
805 with file(H_file, 'r') as original: data = original.read() |
805 with file(H_file, 'r') as original: data = original.read() |
806 with file(H_file, 'w') as modified: modified.write('#include "beremiz.h"\n' + data) |
806 with file(H_file, 'w') as modified: modified.write('#include "beremiz.h"\n' + data) |
827 # Get classname instance |
827 # Get classname instance |
828 self._builder = targetclass(self) |
828 self._builder = targetclass(self) |
829 return self._builder |
829 return self._builder |
830 |
830 |
831 def ResetBuildMD5(self): |
831 def ResetBuildMD5(self): |
832 builder=self.GetBuilder() |
832 builder = self.GetBuilder() |
833 if builder is not None: |
833 if builder is not None: |
834 builder.ResetBinaryCodeMD5() |
834 builder.ResetBinaryCodeMD5() |
835 self.EnableMethod("_Transfer", False) |
835 self.EnableMethod("_Transfer", False) |
836 |
836 |
837 def GetLastBuildMD5(self): |
837 def GetLastBuildMD5(self): |
838 builder=self.GetBuilder() |
838 builder = self.GetBuilder() |
839 if builder is not None: |
839 if builder is not None: |
840 return builder.GetBinaryCodeMD5() |
840 return builder.GetBinaryCodeMD5() |
841 else: |
841 else: |
842 return None |
842 return None |
843 |
843 |
931 config_FBs[tuple(parts)] = attrs["C_path"] |
931 config_FBs[tuple(parts)] = attrs["C_path"] |
932 if attrs["vartype"] != "FB" and attrs["type"] in DebugTypesSize: |
932 if attrs["vartype"] != "FB" and attrs["type"] in DebugTypesSize: |
933 # Push this dictionnary into result. |
933 # Push this dictionnary into result. |
934 self._DbgVariablesList.append(attrs) |
934 self._DbgVariablesList.append(attrs) |
935 # Fill in IEC<->C translation dicts |
935 # Fill in IEC<->C translation dicts |
936 IEC_path=attrs["IEC_path"] |
936 IEC_path = attrs["IEC_path"] |
937 self._IECPathToIdx[IEC_path]=(Idx, attrs["type"]) |
937 self._IECPathToIdx[IEC_path] = (Idx, attrs["type"]) |
938 # Ignores numbers given in CSV file |
938 # Ignores numbers given in CSV file |
939 # Idx=int(attrs["num"]) |
939 # Idx=int(attrs["num"]) |
940 # Count variables only, ignore FBs |
940 # Count variables only, ignore FBs |
941 Idx+=1 |
941 Idx += 1 |
942 self._VariablesList.append(attrs) |
942 self._VariablesList.append(attrs) |
943 |
943 |
944 # third section contains ticktime |
944 # third section contains ticktime |
945 if len(ListGroup) > 2: |
945 if len(ListGroup) > 2: |
946 self._Ticktime = int(ListGroup[2][0]) |
946 self._Ticktime = int(ListGroup[2][0]) |
963 variable_decl_array = [] |
963 variable_decl_array = [] |
964 bofs = 0 |
964 bofs = 0 |
965 for v in self._DbgVariablesList: |
965 for v in self._DbgVariablesList: |
966 sz = DebugTypesSize.get(v["type"], 0) |
966 sz = DebugTypesSize.get(v["type"], 0) |
967 variable_decl_array += [ |
967 variable_decl_array += [ |
968 "{&(%(C_path)s), " % v+ |
968 "{&(%(C_path)s), " % v + |
969 { |
969 { |
970 "EXT": "%(type)s_P_ENUM", |
970 "EXT": "%(type)s_P_ENUM", |
971 "IN": "%(type)s_P_ENUM", |
971 "IN": "%(type)s_P_ENUM", |
972 "MEM": "%(type)s_O_ENUM", |
972 "MEM": "%(type)s_O_ENUM", |
973 "OUT": "%(type)s_O_ENUM", |
973 "OUT": "%(type)s_O_ENUM", |
986 "MEM": "extern __IEC_%(type)s_p %(C_path)s;", |
986 "MEM": "extern __IEC_%(type)s_p %(C_path)s;", |
987 "OUT": "extern __IEC_%(type)s_p %(C_path)s;", |
987 "OUT": "extern __IEC_%(type)s_p %(C_path)s;", |
988 "VAR": "extern __IEC_%(type)s_t %(C_path)s;", |
988 "VAR": "extern __IEC_%(type)s_t %(C_path)s;", |
989 "FB": "extern %(type)s %(C_path)s;" |
989 "FB": "extern %(type)s %(C_path)s;" |
990 }[v["vartype"]] % v |
990 }[v["vartype"]] % v |
991 for v in self._VariablesList if v["C_path"].find('.')<0]), |
991 for v in self._VariablesList if v["C_path"].find('.') < 0]), |
992 "variable_decl_array": ",\n".join(variable_decl_array) |
992 "variable_decl_array": ",\n".join(variable_decl_array) |
993 } |
993 } |
994 |
994 |
995 return debug_code |
995 return debug_code |
996 |
996 |
1006 |
1006 |
1007 # Generate main, based on template |
1007 # Generate main, based on template |
1008 if not self.BeremizRoot.getDisable_Extensions(): |
1008 if not self.BeremizRoot.getDisable_Extensions(): |
1009 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1009 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1010 "calls_prototypes": "\n".join([( |
1010 "calls_prototypes": "\n".join([( |
1011 "int __init_%(s)s(int argc,char **argv);\n"+ |
1011 "int __init_%(s)s(int argc,char **argv);\n" + |
1012 "void __cleanup_%(s)s(void);\n"+ |
1012 "void __cleanup_%(s)s(void);\n" + |
1013 "void __retrieve_%(s)s(void);\n"+ |
1013 "void __retrieve_%(s)s(void);\n" + |
1014 "void __publish_%(s)s(void);") % {'s': locstr} for locstr in locstrs]), |
1014 "void __publish_%(s)s(void);") % {'s': locstr} for locstr in locstrs]), |
1015 "retrieve_calls": "\n ".join([ |
1015 "retrieve_calls": "\n ".join([ |
1016 "__retrieve_%s();" % locstr for locstr in locstrs]), |
1016 "__retrieve_%s();" % locstr for locstr in locstrs]), |
1017 "publish_calls": "\n ".join([ # Call publish in reverse order |
1017 "publish_calls": "\n ".join([ # Call publish in reverse order |
1018 "__publish_%s();" % locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]), |
1018 "__publish_%s();" % locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]), |
1019 "init_calls": "\n ".join([ |
1019 "init_calls": "\n ".join([ |
1020 "init_level=%d; " % (i+1)+ |
1020 "init_level=%d; " % (i+1) + |
1021 "if((res = __init_%s(argc,argv))){" % locstr + |
1021 "if((res = __init_%s(argc,argv))){" % locstr + |
1022 #"printf(\"%s\"); "%locstr + #for debug |
1022 #"printf(\"%s\"); "%locstr + #for debug |
1023 "return res;}" for i, locstr in enumerate(locstrs)]), |
1023 "return res;}" for i, locstr in enumerate(locstrs)]), |
1024 "cleanup_calls": "\n ".join([ |
1024 "cleanup_calls": "\n ".join([ |
1025 "if(init_level >= %d) " % i+ |
1025 "if(init_level >= %d) " % i + |
1026 "__cleanup_%s();" % locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]) |
1026 "__cleanup_%s();" % locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]) |
1027 } |
1027 } |
1028 else: |
1028 else: |
1029 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1029 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1030 "calls_prototypes": "\n", |
1030 "calls_prototypes": "\n", |
1393 [list() for n in xrange(len(self.TracedIECPath))]) |
1393 [list() for n in xrange(len(self.TracedIECPath))]) |
1394 ticks, self.DebugTicks = self.DebugTicks, [] |
1394 ticks, self.DebugTicks = self.DebugTicks, [] |
1395 return ticks, buffers |
1395 return ticks, buffers |
1396 |
1396 |
1397 def RegisterDebugVarToConnector(self): |
1397 def RegisterDebugVarToConnector(self): |
1398 self.DebugTimer=None |
1398 self.DebugTimer = None |
1399 Idxs = [] |
1399 Idxs = [] |
1400 self.TracedIECPath = [] |
1400 self.TracedIECPath = [] |
1401 self.TracedIECTypes = [] |
1401 self.TracedIECTypes = [] |
1402 if self._connector is not None: |
1402 if self._connector is not None: |
1403 self.IECdebug_lock.acquire() |
1403 self.IECdebug_lock.acquire() |
1444 # If an output location var is forced it's leads to segmentation fault in runtime |
1444 # If an output location var is forced it's leads to segmentation fault in runtime |
1445 # Links between PLC located variables and real variables are not ready |
1445 # Links between PLC located variables and real variables are not ready |
1446 if self.IsPLCStarted(): |
1446 if self.IsPLCStarted(): |
1447 # Timer to prevent rapid-fire when registering many variables |
1447 # Timer to prevent rapid-fire when registering many variables |
1448 # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead |
1448 # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead |
1449 self.DebugTimer=Timer(0.5, wx.CallAfter, args = [self.RegisterDebugVarToConnector]) |
1449 self.DebugTimer = Timer(0.5, wx.CallAfter, args = [self.RegisterDebugVarToConnector]) |
1450 # Rearm anti-rapid-fire timer |
1450 # Rearm anti-rapid-fire timer |
1451 self.DebugTimer.start() |
1451 self.DebugTimer.start() |
1452 |
1452 |
1453 def GetDebugIECVariableType(self, IECPath): |
1453 def GetDebugIECVariableType(self, IECPath): |
1454 Idx, IEC_Type = self._IECPathToIdx.get(IECPath, (None, None)) |
1454 Idx, IEC_Type = self._IECPathToIdx.get(IECPath, (None, None)) |
1906 }, |
1906 }, |
1907 ] |
1907 ] |
1908 |
1908 |
1909 def EnableMethod(self, method, value): |
1909 def EnableMethod(self, method, value): |
1910 for d in self.StatusMethods: |
1910 for d in self.StatusMethods: |
1911 if d["method"]==method: |
1911 if d["method"] == method: |
1912 d["enabled"]=value |
1912 d["enabled"] = value |
1913 return True |
1913 return True |
1914 return False |
1914 return False |
1915 |
1915 |
1916 def ShowMethod(self, method, value): |
1916 def ShowMethod(self, method, value): |
1917 for d in self.StatusMethods: |
1917 for d in self.StatusMethods: |
1918 if d["method"]==method: |
1918 if d["method"] == method: |
1919 d["shown"]=value |
1919 d["shown"] = value |
1920 return True |
1920 return True |
1921 return False |
1921 return False |
1922 |
1922 |
1923 def CallMethod(self, method): |
1923 def CallMethod(self, method): |
1924 for d in self.StatusMethods: |
1924 for d in self.StatusMethods: |
1925 if d["method"]==method and d.get("enabled", True) and d.get("shown", True): |
1925 if d["method"] == method and d.get("enabled", True) and d.get("shown", True): |
1926 getattr(self, method)() |
1926 getattr(self, method)() |