plugger.py
changeset 110 a05e8b30c024
parent 109 f27ca37b6e7a
child 113 78a92a18f8d6
equal deleted inserted replaced
109:f27ca37b6e7a 110:a05e8b30c024
     6 import plugins
     6 import plugins
     7 import types
     7 import types
     8 import shutil
     8 import shutil
     9 from xml.dom import minidom
     9 from xml.dom import minidom
    10 import wx
    10 import wx
    11 import subprocess, ctypes, time, shutil
       
    12 
    11 
    13 #Quick hack to be able to find Beremiz IEC tools. Should be config params.
    12 #Quick hack to be able to find Beremiz IEC tools. Should be config params.
    14 base_folder = os.path.split(sys.path[0])[0]
    13 base_folder = os.path.split(sys.path[0])[0]
    15 sys.path.append(os.path.join(base_folder, "plcopeneditor"))
    14 sys.path.append(os.path.join(base_folder, "plcopeneditor"))
    16 
    15 
    17 from xmlclass import GenerateClassesFromXSDstring
    16 from xmlclass import GenerateClassesFromXSDstring
       
    17 from wxPopen import ProcessLogger
    18 
    18 
    19 _BaseParamsClass = GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
    19 _BaseParamsClass = GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
    20         <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    20         <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    21           <xsd:element name="BaseParams">
    21           <xsd:element name="BaseParams">
    22             <xsd:complexType>
    22             <xsd:complexType>
   668         self.ProjectPath = None
   668         self.ProjectPath = None
   669         self.PLCEditor = None
   669         self.PLCEditor = None
   670         
   670         
   671         # copy PluginMethods so that it can be later customized
   671         # copy PluginMethods so that it can be later customized
   672         self.PluginMethods = [dic.copy() for dic in self.PluginMethods]
   672         self.PluginMethods = [dic.copy() for dic in self.PluginMethods]
       
   673         
       
   674         self.runningPLC = None
       
   675 
   673     
   676     
   674     def HasProjectOpened(self):
   677     def HasProjectOpened(self):
   675         """
   678         """
   676         Return if a project is actually opened
   679         Return if a project is actually opened
   677         """
   680         """
   858         plc_file.write(open(self._getIECgeneratedcodepath(), "r").read())
   861         plc_file.write(open(self._getIECgeneratedcodepath(), "r").read())
   859         plc_file.close()
   862         plc_file.close()
   860         logger.write("Compiling IEC Program in to C code...\n")
   863         logger.write("Compiling IEC Program in to C code...\n")
   861         # Now compile IEC code into many C files
   864         # Now compile IEC code into many C files
   862         # files are listed to stdout, and errors to stderr. 
   865         # files are listed to stdout, and errors to stderr. 
   863         status, result, err_result = logger.LogCommand("%s \"%s\" -I \"%s\" \"%s\""%(iec2c_path, self._getIECcodepath(), ieclib_path, buildpath), no_stdout=True)
   866         status, result, err_result = ProcessLogger(
       
   867                logger,
       
   868                "%s \"%s\" -I \"%s\" \"%s\""%(
       
   869                          iec2c_path,
       
   870                          self._getIECcodepath(),
       
   871                          ieclib_path, buildpath),
       
   872                no_stdout=True).spin()
   864         if status:
   873         if status:
   865             # Failed !
   874             # Failed !
   866             logger.write_error("Error : IEC to C compiler returned %d\n"%status)
   875             logger.write_error("Error : IEC to C compiler returned %d\n"%status)
   867             return False
   876             return False
   868         # Now extract C files of stdout
   877         # Now extract C files of stdout
   891         if not os.path.exists(buildpath):
   900         if not os.path.exists(buildpath):
   892             os.mkdir(buildpath)
   901             os.mkdir(buildpath)
   893         
   902         
   894         logger.flush()
   903         logger.flush()
   895         logger.write("Start build in %s\n" % buildpath)
   904         logger.write("Start build in %s\n" % buildpath)
       
   905 
       
   906         self.EnableMethod("_Clean", True)
       
   907         self.EnableMethod("_showIECcode", True)
   896         
   908         
   897         # Generate SoftPLC code
   909         # Generate SoftPLC code
   898         if not self._Generate_SoftPLC(logger):
   910         if not self._Generate_SoftPLC(logger):
   899             logger.write_error("SoftPLC code generation failed !\n")
   911             logger.write_error("SoftPLC code generation failed !\n")
   900             return False
   912             return False
       
   913 
   901 
   914 
   902         #logger.write("SoftPLC code generation successfull\n")
   915         #logger.write("SoftPLC code generation successfull\n")
   903 
   916 
   904         logger.write("Generating plugins code ...\n")
   917         logger.write("Generating plugins code ...\n")
   905         
   918         
   958                 bn = os.path.basename(CFile)
   971                 bn = os.path.basename(CFile)
   959                 obn = os.path.splitext(bn)[0]+".o"
   972                 obn = os.path.splitext(bn)[0]+".o"
   960                 obns.append(obn)
   973                 obns.append(obn)
   961                 logger.write("   [CC]  "+bn+" -> "+obn+"\n")
   974                 logger.write("   [CC]  "+bn+" -> "+obn+"\n")
   962                 objectfilename = os.path.splitext(CFile)[0]+".o"
   975                 objectfilename = os.path.splitext(CFile)[0]+".o"
   963                 status, result, err_result = logger.LogCommand("\"%s\" -c \"%s\" -o \"%s\" %s %s"%(compiler, CFile, objectfilename, _CFLAGS, CFLAGS))
   976 
       
   977                 status, result, err_result = ProcessLogger(
       
   978                        logger,
       
   979                        "\"%s\" -c \"%s\" -o \"%s\" %s %s"%
       
   980                            (compiler, CFile, objectfilename, _CFLAGS, CFLAGS)
       
   981                        ).spin()
       
   982 
   964                 if status != 0:
   983                 if status != 0:
   965                     logger.write_error("Build failed\n")
   984                     logger.write_error("Build failed\n")
   966                     return False
   985                     return False
   967                 objs.append(objectfilename)
   986                 objs.append(objectfilename)
   968         # Link all the object files into one executable
   987         # Link all the object files into one executable
   970         exe = self.GetProjectName()
   989         exe = self.GetProjectName()
   971         if target_name == "Win32":
   990         if target_name == "Win32":
   972             exe += ".exe"
   991             exe += ".exe"
   973         exe_path = os.path.join(buildpath, exe)
   992         exe_path = os.path.join(buildpath, exe)
   974         logger.write("   [CC]  " + ' '.join(obns)+" -> " + exe + "\n")
   993         logger.write("   [CC]  " + ' '.join(obns)+" -> " + exe + "\n")
   975         status, result, err_result = logger.LogCommand("\"%s\" \"%s\" -o \"%s\" %s"%(linker, '" "'.join(objs), exe_path, ' '.join(LDFLAGS+[_LDFLAGS])))
   994         status, result, err_result = ProcessLogger(
       
   995                logger,
       
   996                "\"%s\" \"%s\" -o \"%s\" %s"%
       
   997                    (linker,
       
   998                     '" "'.join(objs),
       
   999                     exe_path,
       
  1000                     ' '.join(LDFLAGS+[_LDFLAGS]))
       
  1001                ).spin()
   976         if status != 0:
  1002         if status != 0:
   977             logger.write_error("Build failed\n")
  1003             logger.write_error("Build failed\n")
   978             self.EnableMethod("_Run", False)
  1004             self.EnableMethod("_Run", False)
   979             return False
  1005             return False
   980         
  1006         
  1032         if os.path.isdir(os.path.join(self._getBuildPath())):
  1058         if os.path.isdir(os.path.join(self._getBuildPath())):
  1033             logger.write("Cleaning the build directory\n")
  1059             logger.write("Cleaning the build directory\n")
  1034             shutil.rmtree(os.path.join(self._getBuildPath()))
  1060             shutil.rmtree(os.path.join(self._getBuildPath()))
  1035         else:
  1061         else:
  1036             logger.write_error("Build directory already clean\n")
  1062             logger.write_error("Build directory already clean\n")
       
  1063         self.EnableMethod("_showIECcode", False)
       
  1064         self.EnableMethod("_Clean", False)
       
  1065         self.EnableMethod("_Run", False)
  1037     
  1066     
  1038     def _Run(self, logger):
  1067     def _Run(self, logger):
  1039         logger.write("\n")
       
  1040         self.pid_plc = 0
       
  1041         command_start_plc = os.path.join(self._getBuildPath(),self.GetProjectName() + exe_ext)
  1068         command_start_plc = os.path.join(self._getBuildPath(),self.GetProjectName() + exe_ext)
  1042         if os.path.isfile(command_start_plc):
  1069         if os.path.isfile(command_start_plc):
  1043             logger.write("\nStarting PLC\n")
  1070             logger.write("Starting PLC\n")
  1044             self.pid_plc = subprocess.Popen(command_start_plc).pid
  1071             def this_plc_finish_callback(*args):
       
  1072                 if self.runningPLC is not None:
       
  1073                     self.runningPLC = None
       
  1074                     self._Stop(logger) 
       
  1075             self.runningPLC = ProcessLogger(
       
  1076                logger,
       
  1077                command_start_plc,
       
  1078                finish_callback = this_plc_finish_callback)
       
  1079             self.EnableMethod("_Clean", False)
       
  1080             self.EnableMethod("_Run", False)
       
  1081             self.EnableMethod("_Stop", True)
       
  1082             self.EnableMethod("_build", False)
  1045         else:
  1083         else:
  1046             logger.write_error("%s doesn't exist\n" %command_start_plc)
  1084             logger.write_error("%s doesn't exist\n" %command_start_plc)
  1047 
  1085 
       
  1086     def reset_finished(self):
       
  1087         self.EnableMethod("_Clean", True)
       
  1088         self.EnableMethod("_Run", True)
       
  1089         self.EnableMethod("_Stop", False)
       
  1090         self.EnableMethod("_build", True)
       
  1091 
  1048     def _Stop(self, logger):
  1092     def _Stop(self, logger):
  1049         PROCESS_TERMINATE = 1
  1093         if self.runningPLC is not None:
  1050         if self.pid_plc != 0:
       
  1051             logger.write("Stopping PLC\n")
  1094             logger.write("Stopping PLC\n")
  1052             handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, self.pid_plc)
  1095             was_runningPLC = self.runningPLC 
  1053             ctypes.windll.kernel32.TerminateProcess(handle, -1)
  1096             self.runningPLC = None
  1054             ctypes.windll.kernel32.CloseHandle(handle)
  1097             was_runningPLC.kill()
       
  1098             self.reset_finished()
  1055 
  1099 
  1056     PluginMethods = [
  1100     PluginMethods = [
  1057         {"bitmap" : os.path.join("images", "editPLC"),
  1101         {"bitmap" : os.path.join("images", "editPLC"),
  1058          "name" : "Edit PLC",
  1102          "name" : "Edit PLC",
  1059          "tooltip" : "Edit PLC program with PLCOpenEditor",
  1103          "tooltip" : "Edit PLC program with PLCOpenEditor",
  1076          "enabled" : False,
  1120          "enabled" : False,
  1077          "tooltip" : "Stop Running PLC",
  1121          "tooltip" : "Stop Running PLC",
  1078          "method" : "_Stop"},
  1122          "method" : "_Stop"},
  1079         {"bitmap" : os.path.join("images", "ShowIECcode"),
  1123         {"bitmap" : os.path.join("images", "ShowIECcode"),
  1080          "name" : "Show IEC code",
  1124          "name" : "Show IEC code",
       
  1125          "enabled" : False,
  1081          "tooltip" : "Show IEC code generated by PLCGenerator",
  1126          "tooltip" : "Show IEC code generated by PLCGenerator",
  1082          "method" : "_showIECcode"},
  1127          "method" : "_showIECcode"},
  1083         {"name" : "Edit raw IEC code",
  1128         {"name" : "Edit raw IEC code",
  1084          "tooltip" : "Edit raw IEC code added to code generated by PLCGenerator",
  1129          "tooltip" : "Edit raw IEC code added to code generated by PLCGenerator",
  1085          "method" : "_editIECrawcode"}
  1130          "method" : "_editIECrawcode"}
  1086     ]
  1131     ]
  1087