--- a/LPCBeremiz.py Wed Dec 09 16:52:46 2009 +0100
+++ b/LPCBeremiz.py Wed Dec 09 16:53:27 2009 +0100
@@ -62,7 +62,7 @@
__builtin__.__dict__['_'] = wx.GetTranslation#unicode_translation
-from plugger import PluginsRoot, PlugTemplate, opjimg
+from plugger import PluginsRoot, PlugTemplate, opjimg, connectors from plcopen.structures import LOCATIONDATATYPES
from PLCControler import LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP,\
LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
@@ -355,10 +355,10 @@
class LPCPluginsRoot(PluginsRoot):
- {"bitmap" : opjimg("Build"),
- "tooltip" : _("Build project into build folder"),
+ {"bitmap" : opjimg("Debug"), + "name" : _("Simulate"), + "tooltip" : _("Simulate PLC"), + "method" : "_Simulate"}, {"bitmap" : opjimg("Run"),
@@ -369,6 +369,10 @@
"tooltip" : _("Stop Running PLC"),
+ {"bitmap" : opjimg("Build"), + "tooltip" : _("Build project into build folder"), {"bitmap" : opjimg("Transfer"),
@@ -383,24 +387,87 @@
+ self.BuildSimulation = False + self.SimulationBuildPath = None + self.previous_simulating = False def GetProjectName(self):
return self.Project.getname()
def GetDefaultTarget(self):
target = self.Classes["BeremizRoot_TargetType"]()
- target_value = self.Classes["TargetType_LPC"]()
- target_value.setBuildPath(self.BuildPath)
- target.setcontent({"name": "Makefile", "value": target_value})
+ if self.BuildSimulation: + if wx.Platform == '__WXMSW__': + target_value = self.Classes["TargetType_%s"%target_name]() + target_value = self.Classes["TargetType_LPC"]() + target_value.setBuildPath(self.BuildPath) + target.setcontent({"name": target_name, "value": target_value})
+ def _getBuildPath(self): + if self.BuildSimulation: + if self.SimulationBuildPath is None: + self.SimulationBuildPath = os.path.join(tempfile.mkdtemp(), os.path.basename(self.ProjectPath), "build") + return self.SimulationBuildPath + PluginsRoot._getBuildPath(self) def SetProjectName(self, name):
return self.Project.setname(name)
def SetOnlineMode(self, mode, path=None):
- self.UpdateMethodsFromPLCStatus()
+ if self.OnlineMode != mode: + if self.OnLineMode != 0: + if self._connector is None: + uri = "LPC://%s" % path + self._connector = connectors.ConnectorFactory(uri, self) + self.logger.write_error(_("Exception while connecting %s!\n")%uri) + self.logger.write_error(traceback.format_exc()) + # Did connection success ? + if self._connector is None: + self.logger.write_error(_("Connection failed to %s!\n")%uri) + if self._connector is not None: + if self.OnLineMode == 1: + self.CompareLocalAndRemotePLC() + # Init with actual PLC status and print it + self.UpdateMethodsFromPLCStatus() + if self.previous_plcstate is not None: + status = _(self.previous_plcstate) + self.logger.write(_("PLC is %s\n")%status) + # Start the status Timer + self.StatusTimer.Start(milliseconds=500, oneShot=False) + if self.previous_plcstate=="Started": + if self.DebugAvailable() and self.GetIECProgramsAndVariables(): + self.logger.write(_("Debug connect matching running PLC\n")) + self.logger.write_warning(_("Debug do not match PLC - stop/transfert/start to re-enable\n")) + self.StatusTimer.Stop() + self.UpdateMethodsFromPLCStatus() # Update a PLCOpenEditor Pou variable name
def UpdateProjectVariableName(self, old_name, new_name):
@@ -450,46 +517,192 @@
self.RefreshPluginsBlockLists()
- self.SaveXMLFile(self.ProjectPath)
############# Real PLC object access #############
def UpdateMethodsFromPLCStatus(self):
# Get PLC state : Running or Stopped
# TODO : use explicit status instead of boolean
+ if self._connector is not None: + simulating = self._connector.GetPLCstatus() == "Started" elif self.OnlineMode == 1:
+ if self._connector is not None: + simulating = self._connector.GetPLCstatus() == "Started" - elif self._connector is not None:
- status = self._connector.GetPLCstatus()
- status = "Disconnected"
- if(self.previous_plcstate != status):
+ if self._connector is not None: + status = self._connector.GetPLCstatus() + status = "Disconnected" + if self.previous_plcstate != status or self.previous_simulating != simulating: - "Started" : [("_build", False),
+ "Started" : [("_Simulate", False), - "Stopped" : [("_build", False),
+ "Stopped" : [("_Simulate", False), - "Connected" : [("_build", False),
+ "Connected" : [("_Simulate", not simulating),
- "Disconnected" :[("_build", True),
+ "Disconnected" :[("_Simulate", not simulating),
self.previous_plcstate = status
+ self.previous_simulating = simulating + def Generate_plc_declare_locations(self): + Declare used locations in order to simulatePLC in a black box + return """#include "iec_types_all.h" +#define __LOCATED_VAR(type, name, ...) \ +type *name = &beremiz_##name; +#include "LOCATED_VARIABLES.h" + Method called by user to Simulate PLC + self._connector = connectors.ConnectorFactory(uri, self) + self.logger.write_error(_("Exception while connecting %s!\n")%uri) + self.logger.write_error(traceback.format_exc()) + # Did connection success ? + if self._connector is None: + self.logger.write_error(_("Connection failed to %s!\n")%uri) + self.BuildSimulation = True + buildpath = self._getBuildPath() + # Eventually create build dir + if not os.path.exists(buildpath): + # Generate SoftPLC IEC code + IECGenRes = self._Generate_SoftPLC() + # If IEC code gen fail, bail out. + self.logger.write_error(_("IEC-61131-3 code generation failed !\n")) + self.BuildSimulation = False + # Reset variable and program list that are parsed from + # CSV file generated by IEC2C compiler. + self.ResetIECProgramsAndVariables() + gen_result = self.PlugGenerate_C(buildpath, self.PLCGeneratedLocatedVars) + PlugCFilesAndCFLAGS, PlugLDFLAGS, DoCalls = gen_result[:3] + # if some files have been generated put them in the list with their location + if PlugCFilesAndCFLAGS: + self.LocationCFilesAndCFLAGS = [(self.GetCurrentLocation(), PlugCFilesAndCFLAGS, DoCalls)] + self.LocationCFilesAndCFLAGS = [] + # plugin asks for some LDFLAGS + # LDFLAGS can be either string + if type(PlugLDFLAGS)==type(str()): + self.LDFLAGS=[PlugLDFLAGS] + elif type(PlugLDFLAGS)==type(list()): + self.LDFLAGS=PlugLDFLAGS[:] + # Template based part of C code generation + # files are stacked at the beginning, as files of plugin tree root + for generator, filename, name in [ + (self.Generate_plc_debugger, "plc_debugger.c", "Debugger"), + # init/cleanup/retrieve/publish, run and align code + (self.Generate_plc_common_main,"plc_common_main.c","Common runtime"), + # declare located variables for simulate in a black box + (self.Generate_plc_declare_locations,"plc_declare_locations.c","Declare Locations")]: + code_path = os.path.join(buildpath,filename) + open(code_path, "w").write(code) + # Insert this file as first file to be compiled at root plugin + self.LocationCFilesAndCFLAGS[0][1].insert(0,(code_path, self.plcCFLAGS)) + self.logger.write_error(name+_(" generation failed !\n")) + self.logger.write_error(traceback.format_exc()) + self.BuildSimulation = False + # Get simulation builder + builder = self.GetBuilder() + self.logger.write_error(_("Fatal : cannot get builder.\n")) + self.BuildSimulation = False + if not builder.build() : + self.logger.write_error(_("C Build failed.\n")) + self.BuildSimulation = False + self.logger.write_error(_("C Build crashed !\n")) + self.logger.write_error(traceback.format_exc()) + self.BuildSimulation = False + data = builder.GetBinaryCode() + if self._connector.NewPLC(builder.GetBinaryCodeMD5(), data, []): + if self.AppFrame is not None: + self.AppFrame.CloseDebugTabs() + self.AppFrame.RefreshInstancesTree() + self.UnsubscribeAllDebugIECVariable() + self.ProgramTransferred() + self.logger.write(_("Transfer completed successfully.\n")) + self.logger.write_error(_("Transfer failed\n")) + self.BuildSimulation = False + self.BuildSimulation = False + # Start the status Timer + self.StatusTimer.Start(milliseconds=500, oneShot=False) #-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
@@ -550,7 +763,10 @@
global frame, lpcberemiz_cmd
self.PluginRoot.ResetAppFrame(lpcberemiz_cmd.Log)
+ if self.PluginRoot.OnlineMode == 0: + self.PluginRoot._connector = None + self.PluginRoot.KillDebugThread() @@ -754,7 +970,7 @@
# Install a exception handle for bug reports
AddExceptHook(os.getcwd(),__version__)
- frame = LPCBeremiz(None, plugin_root=plugin_root, debug=False)
+ frame = LPCBeremiz(None, plugin_root=plugin_root, debug=True) plugin_root.SetAppFrame(frame, frame.Log)