68 ITEM_CONFNODE = 25 |
68 ITEM_CONFNODE = 25 |
69 |
69 |
70 |
70 |
71 def ExtractChildrenTypesFromCatalog(catalog): |
71 def ExtractChildrenTypesFromCatalog(catalog): |
72 children_types = [] |
72 children_types = [] |
73 for n,d,h,c in catalog: |
73 for n, d, h, c in catalog: |
74 if isinstance(c, ListType): |
74 if isinstance(c, ListType): |
75 children_types.extend(ExtractChildrenTypesFromCatalog(c)) |
75 children_types.extend(ExtractChildrenTypesFromCatalog(c)) |
76 else: |
76 else: |
77 children_types.append((n, GetClassImporter(c), d)) |
77 children_types.append((n, GetClassImporter(c), d)) |
78 return children_types |
78 return children_types |
79 |
79 |
80 |
80 |
81 def ExtractMenuItemsFromCatalog(catalog): |
81 def ExtractMenuItemsFromCatalog(catalog): |
82 menu_items = [] |
82 menu_items = [] |
83 for n,d,h,c in catalog: |
83 for n, d, h, c in catalog: |
84 if isinstance(c, ListType): |
84 if isinstance(c, ListType): |
85 children = ExtractMenuItemsFromCatalog(c) |
85 children = ExtractMenuItemsFromCatalog(c) |
86 else: |
86 else: |
87 children = [] |
87 children = [] |
88 menu_items.append((n, d, h, children)) |
88 menu_items.append((n, d, h, children)) |
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"] |
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"/> |
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) |
270 |
270 |
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): |
586 if getattr(self, "Children", None) is not None: |
586 if getattr(self, "Children", None) is not None: |
587 self.ClearConfNodeTypes() |
587 self.ClearConfNodeTypes() |
666 # define name for IEC raw code file |
666 # define name for IEC raw code file |
667 return os.path.join(self.CTNPath(), "raw_plc.st") |
667 return os.path.join(self.CTNPath(), "raw_plc.st") |
668 |
668 |
669 def GetLocations(self): |
669 def GetLocations(self): |
670 locations = [] |
670 locations = [] |
671 filepath = os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h") |
671 filepath = os.path.join(self._getBuildPath(), "LOCATED_VARIABLES.h") |
672 if os.path.isfile(filepath): |
672 if os.path.isfile(filepath): |
673 # IEC2C compiler generate a list of located variables : LOCATED_VARIABLES.h |
673 # IEC2C compiler generate a list of located variables : LOCATED_VARIABLES.h |
674 location_file = open(os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h")) |
674 location_file = open(os.path.join(self._getBuildPath(), "LOCATED_VARIABLES.h")) |
675 # each line of LOCATED_VARIABLES.h declares a located variable |
675 # each line of LOCATED_VARIABLES.h declares a located variable |
676 lines = [line.strip() for line in location_file.readlines()] |
676 lines = [line.strip() for line in location_file.readlines()] |
677 # This regular expression parses the lines genereated by IEC2C |
677 # This regular expression parses the lines genereated by IEC2C |
678 LOCATED_MODEL = re.compile("__LOCATED_VAR\((?P<IEC_TYPE>[A-Z]*),(?P<NAME>[_A-Za-z0-9]*),(?P<DIR>[QMI])(?:,(?P<SIZE>[XBWDL]))?,(?P<LOC>[,0-9]*)\)") |
678 LOCATED_MODEL = re.compile("__LOCATED_VAR\((?P<IEC_TYPE>[A-Z]*),(?P<NAME>[_A-Za-z0-9]*),(?P<DIR>[QMI])(?:,(?P<SIZE>[XBWDL]))?,(?P<LOC>[,0-9]*)\)") |
679 for line in lines: |
679 for line in lines: |
681 result = LOCATED_MODEL.match(line) |
681 result = LOCATED_MODEL.match(line) |
682 if result: |
682 if result: |
683 # Get the resulting dict |
683 # Get the resulting dict |
684 resdict = result.groupdict() |
684 resdict = result.groupdict() |
685 # rewrite string for variadic location as a tuple of integers |
685 # rewrite string for variadic location as a tuple of integers |
686 resdict['LOC'] = tuple(map(int,resdict['LOC'].split(','))) |
686 resdict['LOC'] = tuple(map(int, resdict['LOC'].split(','))) |
687 # set located size to 'X' if not given |
687 # set located size to 'X' if not given |
688 if not resdict['SIZE']: |
688 if not resdict['SIZE']: |
689 resdict['SIZE'] = 'X' |
689 resdict['SIZE'] = 'X' |
690 # finally store into located variable list |
690 # finally store into located variable list |
691 locations.append(resdict) |
691 locations.append(resdict) |
795 C_files.remove("POUS.c") |
795 C_files.remove("POUS.c") |
796 if not C_files: |
796 if not C_files: |
797 self.logger.write_error(_("Error : At least one configuration and one resource must be declared in PLC !\n")) |
797 self.logger.write_error(_("Error : At least one configuration and one resource must be declared in PLC !\n")) |
798 return False |
798 return False |
799 # transform those base names to full names with path |
799 # transform those base names to full names with path |
800 C_files = map(lambda filename:os.path.join(buildpath, filename), C_files) |
800 C_files = map(lambda filename: os.path.join(buildpath, filename), C_files) |
801 |
801 |
802 # prepend beremiz include to configuration header |
802 # prepend beremiz include to configuration header |
803 H_files = [ fname for fname in result.splitlines() if fname[-2:]==".h" or fname[-2:]==".H" ] |
803 H_files = [ fname for fname in result.splitlines() if fname[-2:]==".h" or fname[-2:]==".H" ] |
804 H_files.remove("LOCATED_VARIABLES.h") |
804 H_files.remove("LOCATED_VARIABLES.h") |
805 H_files = map(lambda filename:os.path.join(buildpath, filename), H_files) |
805 H_files = map(lambda filename: os.path.join(buildpath, filename), H_files) |
806 for H_file in H_files: |
806 for H_file in H_files: |
807 with file(H_file, 'r') as original: data = original.read() |
807 with file(H_file, 'r') as original: data = original.read() |
808 with file(H_file, 'w') as modified: modified.write('#include "beremiz.h"\n' + data) |
808 with file(H_file, 'w') as modified: modified.write('#include "beremiz.h"\n' + data) |
809 |
809 |
810 self.logger.write(_("Extracting Located Variables...\n")) |
810 self.logger.write(_("Extracting Located Variables...\n")) |
881 Each section is marked with a line staring with '//' |
881 Each section is marked with a line staring with '//' |
882 list of all variables used in various POUs |
882 list of all variables used in various POUs |
883 """ |
883 """ |
884 if self._ProgramList is None or self._VariablesList is None: |
884 if self._ProgramList is None or self._VariablesList is None: |
885 try: |
885 try: |
886 csvfile = os.path.join(self._getBuildPath(),"VARIABLES.csv") |
886 csvfile = os.path.join(self._getBuildPath(), "VARIABLES.csv") |
887 # describes CSV columns |
887 # describes CSV columns |
888 ProgramsListAttributeName = ["num", "C_path", "type"] |
888 ProgramsListAttributeName = ["num", "C_path", "type"] |
889 VariablesListAttributeName = ["num", "vartype", "IEC_path", "C_path", "type"] |
889 VariablesListAttributeName = ["num", "vartype", "IEC_path", "C_path", "type"] |
890 self._ProgramList = [] |
890 self._ProgramList = [] |
891 self._VariablesList = [] |
891 self._VariablesList = [] |
892 self._DbgVariablesList = [] |
892 self._DbgVariablesList = [] |
893 self._IECPathToIdx = {} |
893 self._IECPathToIdx = {} |
894 |
894 |
895 # Separate sections |
895 # Separate sections |
896 ListGroup = [] |
896 ListGroup = [] |
897 for line in open(csvfile,'r').xreadlines(): |
897 for line in open(csvfile, 'r').xreadlines(): |
898 strippedline = line.strip() |
898 strippedline = line.strip() |
899 if strippedline.startswith("//"): |
899 if strippedline.startswith("//"): |
900 # Start new section |
900 # Start new section |
901 ListGroup.append([]) |
901 ListGroup.append([]) |
902 elif len(strippedline) > 0 and len(ListGroup) > 0: |
902 elif len(strippedline) > 0 and len(ListGroup) > 0: |
904 ListGroup[-1].append(strippedline) |
904 ListGroup[-1].append(strippedline) |
905 |
905 |
906 # first section contains programs |
906 # first section contains programs |
907 for line in ListGroup[0]: |
907 for line in ListGroup[0]: |
908 # Split and Maps each field to dictionnary entries |
908 # Split and Maps each field to dictionnary entries |
909 attrs = dict(zip(ProgramsListAttributeName,line.strip().split(';'))) |
909 attrs = dict(zip(ProgramsListAttributeName, line.strip().split(';'))) |
910 # Truncate "C_path" to remove conf an resources names |
910 # Truncate "C_path" to remove conf an resources names |
911 attrs["C_path"] = '__'.join(attrs["C_path"].split(".",2)[1:]) |
911 attrs["C_path"] = '__'.join(attrs["C_path"].split(".", 2)[1:]) |
912 # Push this dictionnary into result. |
912 # Push this dictionnary into result. |
913 self._ProgramList.append(attrs) |
913 self._ProgramList.append(attrs) |
914 |
914 |
915 # second section contains all variables |
915 # second section contains all variables |
916 config_FBs = {} |
916 config_FBs = {} |
917 Idx = 0 |
917 Idx = 0 |
918 for line in ListGroup[1]: |
918 for line in ListGroup[1]: |
919 # Split and Maps each field to dictionnary entries |
919 # Split and Maps each field to dictionnary entries |
920 attrs = dict(zip(VariablesListAttributeName,line.strip().split(';'))) |
920 attrs = dict(zip(VariablesListAttributeName, line.strip().split(';'))) |
921 # Truncate "C_path" to remove conf an resources names |
921 # Truncate "C_path" to remove conf an resources names |
922 parts = attrs["C_path"].split(".",2) |
922 parts = attrs["C_path"].split(".", 2) |
923 if len(parts) > 2: |
923 if len(parts) > 2: |
924 config_FB = config_FBs.get(tuple(parts[:2])) |
924 config_FB = config_FBs.get(tuple(parts[:2])) |
925 if config_FB: |
925 if config_FB: |
926 parts = [config_FB] + parts[2:] |
926 parts = [config_FB] + parts[2:] |
927 attrs["C_path"] = '.'.join(parts) |
927 attrs["C_path"] = '.'.join(parts) |
966 bofs = 0 |
966 bofs = 0 |
967 for v in self._DbgVariablesList: |
967 for v in self._DbgVariablesList: |
968 sz = DebugTypesSize.get(v["type"], 0) |
968 sz = DebugTypesSize.get(v["type"], 0) |
969 variable_decl_array += [ |
969 variable_decl_array += [ |
970 "{&(%(C_path)s), " % v+ |
970 "{&(%(C_path)s), " % v+ |
971 {"EXT":"%(type)s_P_ENUM", |
971 { |
972 "IN":"%(type)s_P_ENUM", |
972 "EXT": "%(type)s_P_ENUM", |
973 "MEM":"%(type)s_O_ENUM", |
973 "IN": "%(type)s_P_ENUM", |
974 "OUT":"%(type)s_O_ENUM", |
974 "MEM": "%(type)s_O_ENUM", |
975 "VAR":"%(type)s_ENUM"}[v["vartype"]] % v + |
975 "OUT": "%(type)s_O_ENUM", |
976 "}"] |
976 "VAR": "%(type)s_ENUM" |
|
977 }[v["vartype"]] % v + |
|
978 "}"] |
977 bofs += sz |
979 bofs += sz |
978 debug_code = targets.GetCode("plc_debug.c") % { |
980 debug_code = targets.GetCode("plc_debug.c") % { |
979 "buffer_size":bofs, |
981 "buffer_size": bofs, |
980 "programs_declarations": |
982 "programs_declarations": |
981 "\n".join(["extern %(type)s %(C_path)s;" % p for p in self._ProgramList]), |
983 "\n".join(["extern %(type)s %(C_path)s;" % p for p in self._ProgramList]), |
982 "extern_variables_declarations":"\n".join([ |
984 "extern_variables_declarations": "\n".join([ |
983 {"EXT":"extern __IEC_%(type)s_p %(C_path)s;", |
985 { |
984 "IN":"extern __IEC_%(type)s_p %(C_path)s;", |
986 "EXT": "extern __IEC_%(type)s_p %(C_path)s;", |
985 "MEM":"extern __IEC_%(type)s_p %(C_path)s;", |
987 "IN": "extern __IEC_%(type)s_p %(C_path)s;", |
986 "OUT":"extern __IEC_%(type)s_p %(C_path)s;", |
988 "MEM": "extern __IEC_%(type)s_p %(C_path)s;", |
987 "VAR":"extern __IEC_%(type)s_t %(C_path)s;", |
989 "OUT": "extern __IEC_%(type)s_p %(C_path)s;", |
988 "FB":"extern %(type)s %(C_path)s;"}[v["vartype"]] % v |
990 "VAR": "extern __IEC_%(type)s_t %(C_path)s;", |
|
991 "FB": "extern %(type)s %(C_path)s;" |
|
992 }[v["vartype"]] % v |
989 for v in self._VariablesList if v["C_path"].find('.')<0]), |
993 for v in self._VariablesList if v["C_path"].find('.')<0]), |
990 "variable_decl_array": ",\n".join(variable_decl_array) |
994 "variable_decl_array": ",\n".join(variable_decl_array) |
991 } |
995 } |
992 |
996 |
993 return debug_code |
997 return debug_code |
997 Use confnodes layout given in LocationCFilesAndCFLAGS to |
1001 Use confnodes layout given in LocationCFilesAndCFLAGS to |
998 generate glue code that dispatch calls to all confnodes |
1002 generate glue code that dispatch calls to all confnodes |
999 """ |
1003 """ |
1000 # filter location that are related to code that will be called |
1004 # filter location that are related to code that will be called |
1001 # in retreive, publish, init, cleanup |
1005 # in retreive, publish, init, cleanup |
1002 locstrs = map(lambda x:"_".join(map(str,x)), |
1006 locstrs = map(lambda x: "_".join(map(str, x)), |
1003 [loc for loc,Cfiles,DoCalls in self.LocationCFilesAndCFLAGS if loc and DoCalls]) |
1007 [loc for loc, Cfiles, DoCalls in self.LocationCFilesAndCFLAGS if loc and DoCalls]) |
1004 |
1008 |
1005 # Generate main, based on template |
1009 # Generate main, based on template |
1006 if not self.BeremizRoot.getDisable_Extensions(): |
1010 if not self.BeremizRoot.getDisable_Extensions(): |
1007 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1011 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1008 "calls_prototypes":"\n".join([( |
1012 "calls_prototypes": "\n".join([( |
1009 "int __init_%(s)s(int argc,char **argv);\n"+ |
1013 "int __init_%(s)s(int argc,char **argv);\n"+ |
1010 "void __cleanup_%(s)s(void);\n"+ |
1014 "void __cleanup_%(s)s(void);\n"+ |
1011 "void __retrieve_%(s)s(void);\n"+ |
1015 "void __retrieve_%(s)s(void);\n"+ |
1012 "void __publish_%(s)s(void);") % {'s':locstr} for locstr in locstrs]), |
1016 "void __publish_%(s)s(void);") % {'s': locstr} for locstr in locstrs]), |
1013 "retrieve_calls":"\n ".join([ |
1017 "retrieve_calls": "\n ".join([ |
1014 "__retrieve_%s();" % locstr for locstr in locstrs]), |
1018 "__retrieve_%s();" % locstr for locstr in locstrs]), |
1015 "publish_calls":"\n ".join([ #Call publish in reverse order |
1019 "publish_calls": "\n ".join([ # Call publish in reverse order |
1016 "__publish_%s();" % locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]), |
1020 "__publish_%s();" % locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]), |
1017 "init_calls":"\n ".join([ |
1021 "init_calls": "\n ".join([ |
1018 "init_level=%d; " % (i+1)+ |
1022 "init_level=%d; " % (i+1)+ |
1019 "if((res = __init_%s(argc,argv))){" % locstr + |
1023 "if((res = __init_%s(argc,argv))){" % locstr + |
1020 #"printf(\"%s\"); "%locstr + #for debug |
1024 #"printf(\"%s\"); "%locstr + #for debug |
1021 "return res;}" for i,locstr in enumerate(locstrs)]), |
1025 "return res;}" for i, locstr in enumerate(locstrs)]), |
1022 "cleanup_calls":"\n ".join([ |
1026 "cleanup_calls": "\n ".join([ |
1023 "if(init_level >= %d) " % i+ |
1027 "if(init_level >= %d) " % i+ |
1024 "__cleanup_%s();" % locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]) |
1028 "__cleanup_%s();" % locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]) |
1025 } |
1029 } |
1026 else: |
1030 else: |
1027 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1031 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1028 "calls_prototypes":"\n", |
1032 "calls_prototypes": "\n", |
1029 "retrieve_calls":"\n", |
1033 "retrieve_calls": "\n", |
1030 "publish_calls":"\n", |
1034 "publish_calls": "\n", |
1031 "init_calls":"\n", |
1035 "init_calls": "\n", |
1032 "cleanup_calls":"\n" |
1036 "cleanup_calls": "\n" |
1033 } |
1037 } |
1034 plc_main_code += targets.GetTargetCode(self.GetTarget().getcontent().getLocalTag()) |
1038 plc_main_code += targets.GetTargetCode(self.GetTarget().getcontent().getLocalTag()) |
1035 plc_main_code += targets.GetCode("plc_main_tail.c") |
1039 plc_main_code += targets.GetCode("plc_main_tail.c") |
1036 return plc_main_code |
1040 return plc_main_code |
1037 |
1041 |
1038 |
1042 |
1128 if os.path.exists(extrafilespath): |
1132 if os.path.exists(extrafilespath): |
1129 shutil.rmtree(extrafilespath) |
1133 shutil.rmtree(extrafilespath) |
1130 # Recreate directory |
1134 # Recreate directory |
1131 os.mkdir(extrafilespath) |
1135 os.mkdir(extrafilespath) |
1132 # Then write the files |
1136 # Then write the files |
1133 for fname,fobject in ExtraFiles: |
1137 for fname, fobject in ExtraFiles: |
1134 fpath = os.path.join(extrafilespath,fname) |
1138 fpath = os.path.join(extrafilespath, fname) |
1135 open(fpath, "wb").write(fobject.read()) |
1139 open(fpath, "wb").write(fobject.read()) |
1136 # Now we can forget ExtraFiles (will close files object) |
1140 # Now we can forget ExtraFiles (will close files object) |
1137 del ExtraFiles |
1141 del ExtraFiles |
1138 |
1142 |
1139 # Header file for extensions |
1143 # Header file for extensions |
1140 open(os.path.join(buildpath,"beremiz.h"), "w").write(targets.GetHeader()) |
1144 open(os.path.join(buildpath, "beremiz.h"), "w").write(targets.GetHeader()) |
1141 |
1145 |
1142 # Template based part of C code generation |
1146 # Template based part of C code generation |
1143 # files are stacked at the beginning, as files of confnode tree root |
1147 # files are stacked at the beginning, as files of confnode tree root |
1144 for generator, filename, name in [ |
1148 for generator, filename, name in [ |
1145 # debugger code |
1149 # debugger code |
1146 (self.Generate_plc_debugger, "plc_debugger.c", "Debugger"), |
1150 (self.Generate_plc_debugger, "plc_debugger.c", "Debugger"), |
1147 # init/cleanup/retrieve/publish, run and align code |
1151 # init/cleanup/retrieve/publish, run and align code |
1148 (self.Generate_plc_main,"plc_main.c","Common runtime")]: |
1152 (self.Generate_plc_main, "plc_main.c", "Common runtime")]: |
1149 try: |
1153 try: |
1150 # Do generate |
1154 # Do generate |
1151 code = generator() |
1155 code = generator() |
1152 if code is None: |
1156 if code is None: |
1153 raise |
1157 raise |
1154 code_path = os.path.join(buildpath,filename) |
1158 code_path = os.path.join(buildpath, filename) |
1155 open(code_path, "w").write(code) |
1159 open(code_path, "w").write(code) |
1156 # Insert this file as first file to be compiled at root confnode |
1160 # Insert this file as first file to be compiled at root confnode |
1157 self.LocationCFilesAndCFLAGS[0][1].insert(0,(code_path, self.plcCFLAGS)) |
1161 self.LocationCFilesAndCFLAGS[0][1].insert(0, (code_path, self.plcCFLAGS)) |
1158 except Exception, exc: |
1162 except Exception, exc: |
1159 self.logger.write_error(name+_(" generation failed !\n")) |
1163 self.logger.write_error(name+_(" generation failed !\n")) |
1160 self.logger.write_error(traceback.format_exc()) |
1164 self.logger.write_error(traceback.format_exc()) |
1161 self.ResetBuildMD5() |
1165 self.ResetBuildMD5() |
1162 return False |
1166 return False |
1334 if status is None: |
1338 if status is None: |
1335 self._SetConnector(None, False) |
1339 self._SetConnector(None, False) |
1336 status = "Disconnected" |
1340 status = "Disconnected" |
1337 if(self.previous_plcstate != status): |
1341 if(self.previous_plcstate != status): |
1338 for args in { |
1342 for args in { |
1339 "Started": [("_Run", False), |
1343 "Started": [("_Run", False), |
1340 ("_Stop", True)], |
1344 ("_Stop", True)], |
1341 "Stopped": [("_Run", True), |
1345 "Stopped": [("_Run", True), |
1342 ("_Stop", False)], |
1346 ("_Stop", False)], |
1343 "Empty": [("_Run", False), |
1347 "Empty": [("_Run", False), |
1344 ("_Stop", False)], |
1348 ("_Stop", False)], |
1345 "Broken": [], |
1349 "Broken": [], |
1346 "Disconnected":[("_Run", False), |
1350 "Disconnected": [("_Run", False), |
1347 ("_Stop", False), |
1351 ("_Stop", False), |
1348 ("_Transfer", False), |
1352 ("_Transfer", False), |
1349 ("_Connect", True), |
1353 ("_Connect", True), |
1350 ("_Disconnect", False)], |
1354 ("_Disconnect", False)], |
1351 }.get(status,[]): |
1355 }.get(status, []): |
1352 self.ShowMethod(*args) |
1356 self.ShowMethod(*args) |
1353 self.previous_plcstate = status |
1357 self.previous_plcstate = status |
1354 if self.AppFrame is not None: |
1358 if self.AppFrame is not None: |
1355 updated = True |
1359 updated = True |
1356 self.AppFrame.RefreshStatusToolBar() |
1360 self.AppFrame.RefreshStatusToolBar() |
1400 self.TracedIECPath = [] |
1404 self.TracedIECPath = [] |
1401 self.TracedIECTypes = [] |
1405 self.TracedIECTypes = [] |
1402 if self._connector is not None: |
1406 if self._connector is not None: |
1403 self.IECdebug_lock.acquire() |
1407 self.IECdebug_lock.acquire() |
1404 IECPathsToPop = [] |
1408 IECPathsToPop = [] |
1405 for IECPath,data_tuple in self.IECdebug_datas.iteritems(): |
1409 for IECPath, data_tuple in self.IECdebug_datas.iteritems(): |
1406 WeakCallableDict, data_log, status, fvalue, buffer_list = data_tuple |
1410 WeakCallableDict, data_log, status, fvalue, buffer_list = data_tuple |
1407 if len(WeakCallableDict) == 0: |
1411 if len(WeakCallableDict) == 0: |
1408 # Callable Dict is empty. |
1412 # Callable Dict is empty. |
1409 # This variable is not needed anymore! |
1413 # This variable is not needed anymore! |
1410 IECPathsToPop.append(IECPath) |
1414 IECPathsToPop.append(IECPath) |
1411 elif IECPath != "__tick__": |
1415 elif IECPath != "__tick__": |
1412 # Convert |
1416 # Convert |
1413 Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None)) |
1417 Idx, IEC_Type = self._IECPathToIdx.get(IECPath, (None, None)) |
1414 if Idx is not None: |
1418 if Idx is not None: |
1415 if IEC_Type in DebugTypesSize: |
1419 if IEC_Type in DebugTypesSize: |
1416 Idxs.append((Idx, IEC_Type, fvalue, IECPath)) |
1420 Idxs.append((Idx, IEC_Type, fvalue, IECPath)) |
1417 else: |
1421 else: |
1418 self.logger.write_warning(_("Debug: Unsupported type to debug '%s'\n") % IEC_Type) |
1422 self.logger.write_warning(_("Debug: Unsupported type to debug '%s'\n") % IEC_Type) |
1444 # If an output location var is forced it's leads to segmentation fault in runtime |
1448 # 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 |
1449 # Links between PLC located variables and real variables are not ready |
1446 if self.IsPLCStarted(): |
1450 if self.IsPLCStarted(): |
1447 # Timer to prevent rapid-fire when registering many variables |
1451 # Timer to prevent rapid-fire when registering many variables |
1448 # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead |
1452 # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead |
1449 self.DebugTimer=Timer(0.5,wx.CallAfter,args = [self.RegisterDebugVarToConnector]) |
1453 self.DebugTimer=Timer(0.5, wx.CallAfter, args = [self.RegisterDebugVarToConnector]) |
1450 # Rearm anti-rapid-fire timer |
1454 # Rearm anti-rapid-fire timer |
1451 self.DebugTimer.start() |
1455 self.DebugTimer.start() |
1452 |
1456 |
1453 def GetDebugIECVariableType(self, IECPath): |
1457 def GetDebugIECVariableType(self, IECPath): |
1454 Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None)) |
1458 Idx, IEC_Type = self._IECPathToIdx.get(IECPath, (None, None)) |
1455 return IEC_Type |
1459 return IEC_Type |
1456 |
1460 |
1457 def SubscribeDebugIECVariable(self, IECPath, callableobj, buffer_list=False): |
1461 def SubscribeDebugIECVariable(self, IECPath, callableobj, buffer_list=False): |
1458 """ |
1462 """ |
1459 Dispatching use a dictionnary linking IEC variable paths |
1463 Dispatching use a dictionnary linking IEC variable paths |
1487 |
1491 |
1488 def UnsubscribeDebugIECVariable(self, IECPath, callableobj): |
1492 def UnsubscribeDebugIECVariable(self, IECPath, callableobj): |
1489 self.IECdebug_lock.acquire() |
1493 self.IECdebug_lock.acquire() |
1490 IECdebug_data = self.IECdebug_datas.get(IECPath, None) |
1494 IECdebug_data = self.IECdebug_datas.get(IECPath, None) |
1491 if IECdebug_data is not None: |
1495 if IECdebug_data is not None: |
1492 IECdebug_data[0].pop(callableobj,None) |
1496 IECdebug_data[0].pop(callableobj, None) |
1493 if len(IECdebug_data[0]) == 0: |
1497 if len(IECdebug_data[0]) == 0: |
1494 self.IECdebug_datas.pop(IECPath) |
1498 self.IECdebug_datas.pop(IECPath) |
1495 else: |
1499 else: |
1496 IECdebug_data[4] = reduce( |
1500 IECdebug_data[4] = reduce( |
1497 lambda x, y: x|y, |
1501 lambda x, y: x|y, |
1541 def CallWeakcallables(self, IECPath, function_name, *cargs): |
1545 def CallWeakcallables(self, IECPath, function_name, *cargs): |
1542 data_tuple = self.IECdebug_datas.get(IECPath, None) |
1546 data_tuple = self.IECdebug_datas.get(IECPath, None) |
1543 if data_tuple is not None: |
1547 if data_tuple is not None: |
1544 WeakCallableDict, data_log, status, fvalue, buffer_list = data_tuple |
1548 WeakCallableDict, data_log, status, fvalue, buffer_list = data_tuple |
1545 #data_log.append((debug_tick, value)) |
1549 #data_log.append((debug_tick, value)) |
1546 for weakcallable,buffer_list in WeakCallableDict.iteritems(): |
1550 for weakcallable, buffer_list in WeakCallableDict.iteritems(): |
1547 function = getattr(weakcallable, function_name, None) |
1551 function = getattr(weakcallable, function_name, None) |
1548 if function is not None: |
1552 if function is not None: |
1549 if buffer_list: |
1553 if buffer_list: |
1550 function(*cargs) |
1554 function(*cargs) |
1551 else: |
1555 else: |