38 import tempfile |
38 import tempfile |
39 import hashlib |
39 import hashlib |
40 from datetime import datetime |
40 from datetime import datetime |
41 from weakref import WeakKeyDictionary |
41 from weakref import WeakKeyDictionary |
42 from functools import reduce |
42 from functools import reduce |
43 from itertools import izip |
43 |
44 from distutils.dir_util import copy_tree |
44 from distutils.dir_util import copy_tree |
45 from six.moves import xrange |
45 from six.moves import xrange |
46 |
46 |
47 import wx |
47 import wx |
48 |
48 |
632 for lib in self.Libraries: |
632 for lib in self.Libraries: |
633 res = lib.Generate_C(buildpath, self._VariablesList, LibIECCflags) |
633 res = lib.Generate_C(buildpath, self._VariablesList, LibIECCflags) |
634 LocatedCCodeAndFlags.append(res[:2]) |
634 LocatedCCodeAndFlags.append(res[:2]) |
635 if len(res) > 2: |
635 if len(res) > 2: |
636 Extras.extend(res[2:]) |
636 Extras.extend(res[2:]) |
637 return map(list, zip(*LocatedCCodeAndFlags)) + [tuple(Extras)] |
637 return list(map(list, list(zip(*LocatedCCodeAndFlags)))) + [tuple(Extras)] |
638 |
638 |
639 # Update PLCOpenEditor ConfNode Block types from loaded confnodes |
639 # Update PLCOpenEditor ConfNode Block types from loaded confnodes |
640 def RefreshConfNodesBlockLists(self): |
640 def RefreshConfNodesBlockLists(self): |
641 if getattr(self, "Children", None) is not None: |
641 if getattr(self, "Children", None) is not None: |
642 self.ClearConfNodeTypes() |
642 self.ClearConfNodeTypes() |
886 if not C_files: |
886 if not C_files: |
887 self.logger.write_error( |
887 self.logger.write_error( |
888 _("Error : At least one configuration and one resource must be declared in PLC !\n")) |
888 _("Error : At least one configuration and one resource must be declared in PLC !\n")) |
889 return False |
889 return False |
890 # transform those base names to full names with path |
890 # transform those base names to full names with path |
891 C_files = map( |
891 C_files = [os.path.join(buildpath, filename) for filename in C_files] |
892 lambda filename: os.path.join(buildpath, filename), C_files) |
|
893 |
892 |
894 # prepend beremiz include to configuration header |
893 # prepend beremiz include to configuration header |
895 H_files = [fname for fname in result.splitlines() if fname[ |
894 H_files = [fname for fname in result.splitlines() if fname[ |
896 -2:] == ".h" or fname[-2:] == ".H"] |
895 -2:] == ".h" or fname[-2:] == ".H"] |
897 H_files.remove("LOCATED_VARIABLES.h") |
896 H_files.remove("LOCATED_VARIABLES.h") |
898 H_files = map( |
897 H_files = [os.path.join(buildpath, filename) for filename in H_files] |
899 lambda filename: os.path.join(buildpath, filename), H_files) |
|
900 for H_file in H_files: |
898 for H_file in H_files: |
901 with open(H_file, 'r') as original: |
899 with open(H_file, 'r') as original: |
902 data = original.read() |
900 data = original.read() |
903 with open(H_file, 'w') as modified: |
901 with open(H_file, 'w') as modified: |
904 modified.write('#include "beremiz.h"\n' + data) |
902 modified.write('#include "beremiz.h"\n' + data) |
993 |
991 |
994 # first section contains programs |
992 # first section contains programs |
995 for line in ListGroup[0]: |
993 for line in ListGroup[0]: |
996 # Split and Maps each field to dictionnary entries |
994 # Split and Maps each field to dictionnary entries |
997 attrs = dict( |
995 attrs = dict( |
998 zip(ProgramsListAttributeName, line.strip().split(';'))) |
996 list(zip(ProgramsListAttributeName, line.strip().split(';')))) |
999 # Truncate "C_path" to remove conf an resources names |
997 # Truncate "C_path" to remove conf an resources names |
1000 attrs["C_path"] = '__'.join( |
998 attrs["C_path"] = '__'.join( |
1001 attrs["C_path"].split(".", 2)[1:]) |
999 attrs["C_path"].split(".", 2)[1:]) |
1002 # Push this dictionnary into result. |
1000 # Push this dictionnary into result. |
1003 self._ProgramList.append(attrs) |
1001 self._ProgramList.append(attrs) |
1006 config_FBs = {} |
1004 config_FBs = {} |
1007 Idx = 0 |
1005 Idx = 0 |
1008 for line in ListGroup[1]: |
1006 for line in ListGroup[1]: |
1009 # Split and Maps each field to dictionnary entries |
1007 # Split and Maps each field to dictionnary entries |
1010 attrs = dict( |
1008 attrs = dict( |
1011 zip(VariablesListAttributeName, line.strip().split(';'))) |
1009 list(zip(VariablesListAttributeName, line.strip().split(';')))) |
1012 # Truncate "C_path" to remove conf an resources names |
1010 # Truncate "C_path" to remove conf an resources names |
1013 parts = attrs["C_path"].split(".", 2) |
1011 parts = attrs["C_path"].split(".", 2) |
1014 if len(parts) > 2: |
1012 if len(parts) > 2: |
1015 config_FB = config_FBs.get(tuple(parts[:2])) |
1013 config_FB = config_FBs.get(tuple(parts[:2])) |
1016 if config_FB: |
1014 if config_FB: |
1096 Use confnodes layout given in LocationCFilesAndCFLAGS to |
1094 Use confnodes layout given in LocationCFilesAndCFLAGS to |
1097 generate glue code that dispatch calls to all confnodes |
1095 generate glue code that dispatch calls to all confnodes |
1098 """ |
1096 """ |
1099 # filter location that are related to code that will be called |
1097 # filter location that are related to code that will be called |
1100 # in retreive, publish, init, cleanup |
1098 # in retreive, publish, init, cleanup |
1101 locstrs = map(lambda x: "_".join(map(str, x)), |
1099 locstrs = ["_".join(map(str, x)) for x in [loc for loc, _Cfiles, DoCalls in |
1102 [loc for loc, _Cfiles, DoCalls in |
1100 self.LocationCFilesAndCFLAGS if loc and DoCalls]] |
1103 self.LocationCFilesAndCFLAGS if loc and DoCalls]) |
|
1104 |
1101 |
1105 # Generate main, based on template |
1102 # Generate main, based on template |
1106 if not self.BeremizRoot.getDisable_Extensions(): |
1103 if not self.BeremizRoot.getDisable_Extensions(): |
1107 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1104 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1108 "calls_prototypes": "\n".join([( |
1105 "calls_prototypes": "\n".join([( |
1111 "void __retrieve_%(s)s(void);\n" + |
1108 "void __retrieve_%(s)s(void);\n" + |
1112 "void __publish_%(s)s(void);") % {'s': locstr} for locstr in locstrs]), |
1109 "void __publish_%(s)s(void);") % {'s': locstr} for locstr in locstrs]), |
1113 "retrieve_calls": "\n ".join([ |
1110 "retrieve_calls": "\n ".join([ |
1114 "__retrieve_%s();" % locstr for locstr in locstrs]), |
1111 "__retrieve_%s();" % locstr for locstr in locstrs]), |
1115 "publish_calls": "\n ".join([ # Call publish in reverse order |
1112 "publish_calls": "\n ".join([ # Call publish in reverse order |
1116 "__publish_%s();" % locstrs[i - 1] for i in xrange(len(locstrs), 0, -1)]), |
1113 "__publish_%s();" % locstrs[i - 1] for i in range(len(locstrs), 0, -1)]), |
1117 "init_calls": "\n ".join([ |
1114 "init_calls": "\n ".join([ |
1118 "init_level=%d; " % (i + 1) + |
1115 "init_level=%d; " % (i + 1) + |
1119 "if((res = __init_%s(argc,argv))){" % locstr + |
1116 "if((res = __init_%s(argc,argv))){" % locstr + |
1120 # "printf(\"%s\"); "%locstr + #for debug |
1117 # "printf(\"%s\"); "%locstr + #for debug |
1121 "return res;}" for i, locstr in enumerate(locstrs)]), |
1118 "return res;}" for i, locstr in enumerate(locstrs)]), |
1122 "cleanup_calls": "\n ".join([ |
1119 "cleanup_calls": "\n ".join([ |
1123 "if(init_level >= %d) " % i + |
1120 "if(init_level >= %d) " % i + |
1124 "__cleanup_%s();" % locstrs[i - 1] for i in xrange(len(locstrs), 0, -1)]) |
1121 "__cleanup_%s();" % locstrs[i - 1] for i in range(len(locstrs), 0, -1)]) |
1125 } |
1122 } |
1126 else: |
1123 else: |
1127 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1124 plc_main_code = targets.GetCode("plc_main_head.c") % { |
1128 "calls_prototypes": "\n", |
1125 "calls_prototypes": "\n", |
1129 "retrieve_calls": "\n", |
1126 "retrieve_calls": "\n", |
1393 for extension, edit_name, edit_class in features.file_editors |
1390 for extension, edit_name, edit_class in features.file_editors |
1394 if extension == file_extension]) |
1391 if extension == file_extension]) |
1395 |
1392 |
1396 if editor_name == "": |
1393 if editor_name == "": |
1397 if len(editors) == 1: |
1394 if len(editors) == 1: |
1398 editor_name = editors.keys()[0] |
1395 editor_name = list(editors.keys())[0] |
1399 elif len(editors) > 0: |
1396 elif len(editors) > 0: |
1400 names = editors.keys() |
1397 names = list(editors.keys()) |
1401 dialog = wx.SingleChoiceDialog( |
1398 dialog = wx.SingleChoiceDialog( |
1402 self.AppFrame, |
1399 self.AppFrame, |
1403 _("Select an editor:"), |
1400 _("Select an editor:"), |
1404 _("Editor selection"), |
1401 _("Editor selection"), |
1405 names, |
1402 names, |
1432 self._IECCodeView = None |
1429 self._IECCodeView = None |
1433 if self._IECRawCodeView == view: |
1430 if self._IECRawCodeView == view: |
1434 self._IECRawCodeView = None |
1431 self._IECRawCodeView = None |
1435 if self._ProjectFilesView == view: |
1432 if self._ProjectFilesView == view: |
1436 self._ProjectFilesView = None |
1433 self._ProjectFilesView = None |
1437 if view in self._FileEditors.values(): |
1434 if view in list(self._FileEditors.values()): |
1438 self._FileEditors.pop(view.GetFilePath()) |
1435 self._FileEditors.pop(view.GetFilePath()) |
1439 |
1436 |
1440 def _Clean(self): |
1437 def _Clean(self): |
1441 self._CloseView(self._IECCodeView) |
1438 self._CloseView(self._IECCodeView) |
1442 if os.path.isdir(os.path.join(self._getBuildPath())): |
1439 if os.path.isdir(os.path.join(self._getBuildPath())): |
1504 status = PlcStatus.Disconnected |
1501 status = PlcStatus.Disconnected |
1505 if self.previous_plcstate != status: |
1502 if self.previous_plcstate != status: |
1506 allmethods = self.DefaultMethods.copy() |
1503 allmethods = self.DefaultMethods.copy() |
1507 allmethods.update( |
1504 allmethods.update( |
1508 self.MethodsFromStatus.get(status, {})) |
1505 self.MethodsFromStatus.get(status, {})) |
1509 for method, active in allmethods.items(): |
1506 for method, active in list(allmethods.items()): |
1510 self.ShowMethod(method, active) |
1507 self.ShowMethod(method, active) |
1511 self.previous_plcstate = status |
1508 self.previous_plcstate = status |
1512 if self.AppFrame is not None: |
1509 if self.AppFrame is not None: |
1513 updated = True |
1510 updated = True |
1514 self.AppFrame.RefreshStatusToolBar() |
1511 self.AppFrame.RefreshStatusToolBar() |
1550 if len(Traces) > 0: |
1547 if len(Traces) > 0: |
1551 for debug_tick, debug_buff in Traces: |
1548 for debug_tick, debug_buff in Traces: |
1552 debug_vars = UnpackDebugBuffer( |
1549 debug_vars = UnpackDebugBuffer( |
1553 debug_buff, self.TracedIECTypes) |
1550 debug_buff, self.TracedIECTypes) |
1554 if debug_vars is not None: |
1551 if debug_vars is not None: |
1555 for IECPath, values_buffer, value in izip( |
1552 for IECPath, values_buffer, value in zip( |
1556 self.TracedIECPath, |
1553 self.TracedIECPath, |
1557 self.DebugValuesBuffers, |
1554 self.DebugValuesBuffers, |
1558 debug_vars): |
1555 debug_vars): |
1559 IECdebug_data = self.IECdebug_datas.get( |
1556 IECdebug_data = self.IECdebug_datas.get( |
1560 IECPath, None) |
1557 IECPath, None) |
1576 self.LastComplainDebugToken = self.DebugToken |
1573 self.LastComplainDebugToken = self.DebugToken |
1577 |
1574 |
1578 |
1575 |
1579 |
1576 |
1580 buffers, self.DebugValuesBuffers = (self.DebugValuesBuffers, |
1577 buffers, self.DebugValuesBuffers = (self.DebugValuesBuffers, |
1581 [list() for dummy in xrange(len(self.TracedIECPath))]) |
1578 [list() for dummy in range(len(self.TracedIECPath))]) |
1582 |
1579 |
1583 ticks, self.DebugTicks = self.DebugTicks, [] |
1580 ticks, self.DebugTicks = self.DebugTicks, [] |
1584 |
1581 |
1585 return debug_status, ticks, buffers |
1582 return debug_status, ticks, buffers |
1586 |
1583 |
1601 Idxs = [] |
1598 Idxs = [] |
1602 self.TracedIECPath = [] |
1599 self.TracedIECPath = [] |
1603 self.TracedIECTypes = [] |
1600 self.TracedIECTypes = [] |
1604 if self._connector is not None and self.debug_status != PlcStatus.Broken: |
1601 if self._connector is not None and self.debug_status != PlcStatus.Broken: |
1605 IECPathsToPop = [] |
1602 IECPathsToPop = [] |
1606 for IECPath, data_tuple in self.IECdebug_datas.iteritems(): |
1603 for IECPath, data_tuple in self.IECdebug_datas.items(): |
1607 WeakCallableDict, _data_log, _status, fvalue, _buffer_list = data_tuple |
1604 WeakCallableDict, _data_log, _status, fvalue, _buffer_list = data_tuple |
1608 if len(WeakCallableDict) == 0: |
1605 if len(WeakCallableDict) == 0: |
1609 # Callable Dict is empty. |
1606 # Callable Dict is empty. |
1610 # This variable is not needed anymore! |
1607 # This variable is not needed anymore! |
1611 IECPathsToPop.append(IECPath) |
1608 IECPathsToPop.append(IECPath) |
1625 for IECPathToPop in IECPathsToPop: |
1622 for IECPathToPop in IECPathsToPop: |
1626 self.IECdebug_datas.pop(IECPathToPop) |
1623 self.IECdebug_datas.pop(IECPathToPop) |
1627 |
1624 |
1628 if Idxs: |
1625 if Idxs: |
1629 Idxs.sort() |
1626 Idxs.sort() |
1630 IdxsT = zip(*Idxs) |
1627 IdxsT = list(zip(*Idxs)) |
1631 self.TracedIECPath = IdxsT[3] |
1628 self.TracedIECPath = IdxsT[3] |
1632 self.TracedIECTypes = IdxsT[1] |
1629 self.TracedIECTypes = IdxsT[1] |
1633 res = self._connector.SetTraceVariablesList(zip(*IdxsT[0:3])) |
1630 res = self._connector.SetTraceVariablesList(list(zip(*IdxsT[0:3]))) |
1634 if res is not None and res > 0: |
1631 if res is not None and res > 0: |
1635 self.DebugToken = res |
1632 self.DebugToken = res |
1636 else: |
1633 else: |
1637 self.DebugToken = None |
1634 self.DebugToken = None |
1638 self.logger.write_warning( |
1635 self.logger.write_warning( |
1693 if len(IECdebug_data[0]) == 0: |
1690 if len(IECdebug_data[0]) == 0: |
1694 self.IECdebug_datas.pop(IECPath) |
1691 self.IECdebug_datas.pop(IECPath) |
1695 else: |
1692 else: |
1696 IECdebug_data[4] = reduce( |
1693 IECdebug_data[4] = reduce( |
1697 lambda x, y: x | y, |
1694 lambda x, y: x | y, |
1698 IECdebug_data[0].itervalues(), |
1695 iter(IECdebug_data[0].values()), |
1699 False) |
1696 False) |
1700 |
1697 |
1701 self.AppendDebugUpdate() |
1698 self.AppendDebugUpdate() |
1702 |
1699 |
1703 def UnsubscribeAllDebugIECVariable(self): |
1700 def UnsubscribeAllDebugIECVariable(self): |
1730 def CallWeakcallables(self, IECPath, function_name, *cargs): |
1727 def CallWeakcallables(self, IECPath, function_name, *cargs): |
1731 data_tuple = self.IECdebug_datas.get(IECPath, None) |
1728 data_tuple = self.IECdebug_datas.get(IECPath, None) |
1732 if data_tuple is not None: |
1729 if data_tuple is not None: |
1733 WeakCallableDict, _data_log, _status, _fvalue, buffer_list = data_tuple |
1730 WeakCallableDict, _data_log, _status, _fvalue, buffer_list = data_tuple |
1734 # data_log.append((debug_tick, value)) |
1731 # data_log.append((debug_tick, value)) |
1735 for weakcallable, buffer_list in WeakCallableDict.iteritems(): |
1732 for weakcallable, buffer_list in WeakCallableDict.items(): |
1736 function = getattr(weakcallable, function_name, None) |
1733 function = getattr(weakcallable, function_name, None) |
1737 if function is not None: |
1734 if function is not None: |
1738 # FIXME: apparently, despite of weak ref objects, |
1735 # FIXME: apparently, despite of weak ref objects, |
1739 # some dead C/C++ wx object are still reachable from here |
1736 # some dead C/C++ wx object are still reachable from here |
1740 # leading to RuntimeError exception |
1737 # leading to RuntimeError exception |