33 PluginMethods = [] |
35 PluginMethods = [] |
34 |
36 |
35 def _AddParamsMembers(self): |
37 def _AddParamsMembers(self): |
36 Classes = GenerateClassesFromXSDstring(self.XSD)[0] |
38 Classes = GenerateClassesFromXSDstring(self.XSD)[0] |
37 self.PlugParams = [] |
39 self.PlugParams = [] |
38 for name, XSDclass in Classes.items(): |
40 Classes = [(name, XSDclass) for name, XSDclass in Classes.items() if XSDclass.IsBaseClass] |
39 if XSDclass.IsBaseClass: |
41 if len(Classes) == 1: |
40 obj = XSDclass() |
42 name, XSDclass = Classes[0] |
41 self.PlugParams.append( (name, obj) ) |
43 obj = XSDclass() |
42 setattr(self, name, obj) |
44 self.PlugParams = (name, obj) |
43 |
45 setattr(self, name, obj) |
44 def __init__(self, PlugPath): |
46 |
|
47 def __init__(self): |
45 # Create BaseParam |
48 # Create BaseParam |
46 self.BaseParams = _BaseParamsClass() |
49 self.BaseParams = _BaseParamsClass() |
47 self.MandatoryParams = [("BaseParams", self.BaseParams)] |
50 self.MandatoryParams = ("BaseParams", self.BaseParams) |
48 self._AddParamsMembers() |
51 self._AddParamsMembers() |
49 self.PluggedChilds = {} |
52 self.PluggedChilds = {} |
|
53 |
|
54 def PluginBaseXmlFilePath(self, PlugName=None): |
|
55 return os.path.join(self.PlugPath(PlugName), "baseplugin.xml") |
50 |
56 |
51 def PluginXmlFilePath(self, PlugName=None): |
57 def PluginXmlFilePath(self, PlugName=None): |
52 return os.path.join(self.PlugPath(PlugName), "plugin.xml") |
58 return os.path.join(self.PlugPath(PlugName), "plugin.xml") |
53 |
59 |
54 def PlugPath(self,PlugName=None): |
60 def PlugPath(self,PlugName=None): |
60 return False |
66 return False |
61 |
67 |
62 def OnPlugSave(self): |
68 def OnPlugSave(self): |
63 return True |
69 return True |
64 |
70 |
|
71 def GetPlugParamsAttributes(self): |
|
72 return self.PlugParams[1].getElementAttributes() |
|
73 |
|
74 def SetPlugParamsAttribute(self, name, value): |
|
75 attr = getattr(self.PlugParams[1], name, None) |
|
76 if isinstance(attr, types.ClassType): |
|
77 attr.SetValue(value) |
|
78 else: |
|
79 setattr(self.PlugParams[1], name, value) |
|
80 |
65 def PlugRequestSave(self): |
81 def PlugRequestSave(self): |
66 # If plugin do not have corresponding directory |
82 # If plugin do not have corresponding directory |
67 if not os.path.isdir(self.PlugPath(PlugName)): |
83 plugpath = self.PlugPath() |
|
84 if not os.path.isdir(plugpath): |
68 # Create it |
85 # Create it |
69 os.mkdir(self.PlugPath(PlugName)) |
86 os.mkdir(plugpath) |
70 |
87 |
71 # generate XML for all XML parameters controllers of the plugin |
88 # generate XML for base XML parameters controller of the plugin |
72 XMLString = '<?xml version="1.0" encoding="UTF-8"?>' |
89 basexmlfilepath = self.PluginBaseXmlFilePath() |
73 for nodeName, XMLController in self.PlugParams + self.MandatoryParams: |
90 if basexmlfilepath: |
74 XMLString += XMLController.generateXMLTextMethod(self, nodeName, 0) |
91 BaseXMLFile = open(basexmlfilepath,'w') |
75 XMLFile = open(self.PluginXmlFilePath(PlugName),'w') |
92 BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") |
76 XMLFile.write(XMLString) |
93 BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0)) |
77 XMLFile.close() |
94 BaseXMLFile.close() |
|
95 |
|
96 # generate XML for XML parameters controller of the plugin |
|
97 xmlfilepath = self.PluginXmlFilePath() |
|
98 if xmlfilepath: |
|
99 XMLFile = open(xmlfilepath,'w') |
|
100 XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") |
|
101 XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0)) |
|
102 XMLFile.close() |
78 |
103 |
79 # Call the plugin specific OnPlugSave method |
104 # Call the plugin specific OnPlugSave method |
80 self.OnPlugSave() |
105 result = self.OnPlugSave() |
|
106 if not result: |
|
107 return "Error while saving \"%s\""%self.PlugPath() |
81 |
108 |
82 # go through all childs and do the same |
109 # go through all childs and do the same |
83 for PlugChild in self.IterChilds(): |
110 for PlugChild in self.IterChilds(): |
84 PlugChild.PlugRequestSave() |
111 result = PlugChild.PlugRequestSave() |
|
112 if result: |
|
113 return result |
|
114 return None |
85 |
115 |
86 def PlugImport(self, src_PlugPath): |
116 def PlugImport(self, src_PlugPath): |
87 shutil.copytree(src_PlugPath, self.PlugPath) |
117 shutil.copytree(src_PlugPath, self.PlugPath) |
88 return True |
118 return True |
89 |
119 |
90 def PlugGenerate_C(self, buildpath, current_location, locations): |
120 def PlugGenerate_C(self, buildpath, current_location, locations): |
91 """ |
121 """ |
92 Generate C code |
122 Generate C code |
93 @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) |
123 @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) |
94 @param locations: List of complete variables locations \ |
124 @param locations: List of complete variables locations \ |
95 [(IEC_loc, IEC_Direction IEC_Type, Name)]\ |
125 [(IEC_loc, IEC_Direction, IEC_Type, Name)]\ |
96 ex: [((0,0,4,5),'I','STRING','__IX_0_0_4_5'),...] |
126 ex: [((0,0,4,5),'I','STRING','__IX_0_0_4_5'),...] |
97 """ |
127 """ |
98 return [],"" |
128 return [],"" |
99 |
129 |
100 def _Generate_C(self, buildpath, current_location, locations): |
130 def _Generate_C(self, buildpath, current_location, locations): |
237 # Call the base plugin template init - change XSD into class members |
273 # Call the base plugin template init - change XSD into class members |
238 PlugTemplate.__init__(_self) |
274 PlugTemplate.__init__(_self) |
239 # If dir have already be made, and file exist |
275 # If dir have already be made, and file exist |
240 if os.path.isdir(_self.PlugPath(PlugName)) and os.path.isfile(_self.PluginXmlFilePath(PlugName)): |
276 if os.path.isdir(_self.PlugPath(PlugName)) and os.path.isfile(_self.PluginXmlFilePath(PlugName)): |
241 #Load the plugin.xml file into parameters members |
277 #Load the plugin.xml file into parameters members |
242 _self.LoadXMLParams() |
278 _self.LoadXMLParams(PlugName) |
243 # Check that IEC_Channel is not already in use. |
279 # Check that IEC_Channel is not already in use. |
244 self.FindNewIEC_Channel(self.BaseParams.getIEC_Channel()) |
280 self.FindNewIEC_Channel(self.BaseParams.getIEC_Channel()) |
245 # Call the plugin real __init__ |
281 # Call the plugin real __init__ |
246 PlugClass.__init__(_self) |
282 if getattr(PlugClass, "__init__", None): |
|
283 PlugClass.__init__(_self) |
247 #Load and init all the childs |
284 #Load and init all the childs |
248 _self.LoadChilds() |
285 _self.LoadChilds() |
249 else: |
286 else: |
250 # If plugin do not have corresponding file/dirs - they will be created on Save |
287 # If plugin do not have corresponding file/dirs - they will be created on Save |
251 # Set plugin name |
288 # Set plugin name |
252 _self.BaseParams.setName(PlugName) |
289 _self.BaseParams.setName(PlugName) |
|
290 os.mkdir(_self.PlugPath()) |
253 # Find an IEC number |
291 # Find an IEC number |
254 _self.FindNewIEC_Channel(0) |
292 _self.FindNewIEC_Channel(0) |
255 # Call the plugin real __init__ |
293 # Call the plugin real __init__ |
256 PlugClass.__init__(_self) |
294 if getattr(PlugClass, "__init__", None): |
|
295 PlugClass.__init__(_self) |
|
296 _self.PlugRequestSave() |
257 |
297 |
258 # Create the object out of the resulting class |
298 # Create the object out of the resulting class |
259 newPluginOpj = FinalPlugClass() |
299 newPluginOpj = FinalPlugClass() |
260 # Store it in PluggedChils |
300 # Store it in PluggedChils |
261 PluggedChildsWithSameClass.append(newPluginOpj) |
301 PluggedChildsWithSameClass.append(newPluginOpj) |
262 |
302 |
263 return newPluginOpj |
303 return newPluginOpj |
264 |
304 |
265 |
305 |
266 def LoadXMLParams(self): |
306 def LoadXMLParams(self, PlugName = None, test = True): |
267 # PlugParams have been filled, make a local dict to work with |
307 # Get the base xml tree |
268 PlugParams = dict(self.PlugParams + self.MandatoryParams) |
308 basexmlfilepath = self.PluginBaseXmlFilePath(PlugName) |
|
309 if basexmlfilepath: |
|
310 basexmlfile = open(basexmlfilepath, 'r') |
|
311 basetree = minidom.parse(basexmlfile) |
|
312 self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0]) |
|
313 basexmlfile.close() |
|
314 |
269 # Get the xml tree |
315 # Get the xml tree |
270 xmlfile = open(self.PluginXmlFilePath(PlugName), 'r') |
316 xmlfilepath = self.PluginXmlFilePath(PlugName) |
271 tree = minidom.parse(xmlfile) |
317 if xmlfilepath: |
272 xmlfile.close() |
318 xmlfile = open(xmlfilepath, 'r') |
273 # for each root elements |
319 tree = minidom.parse(xmlfile) |
274 for subtree in tree.childNodes: |
320 self.PlugParams[1].loadXMLTree(tree.childNodes[0]) |
275 # if a plugin specific parameter set |
321 xmlfile.close() |
276 if subtree.nodeName in PlugParams: |
322 |
277 #Load into associated xmlclass. |
323 if test: |
278 PlugParams[subtree.nodeName].loadXMLTree(subtree) |
324 # Basic check. Better to fail immediately. |
279 |
325 if not PlugName: |
280 # Basic check. Better to fail immediately. |
326 PlugName = os.path.split(self.PlugPath())[1].split(NameTypeSeparator)[0] |
281 if(self.BaseParams.getName() != PlugName): |
327 if (self.BaseParams.getName() != PlugName): |
282 raise Exception, "Project tree layout do not match plugin.xml %s!=%s "%(PlugName,self.BaseParams.getName()) |
328 raise Exception, "Project tree layout do not match plugin.xml %s!=%s "%(PlugName, self.BaseParams.getName()) |
283 # Now, self.PlugPath() should be OK |
329 # Now, self.PlugPath() should be OK |
284 |
330 |
285 def LoadChilds(self): |
331 def LoadChilds(self): |
286 # Iterate over all PlugName@PlugType in plugin directory, and try to open them |
332 # Iterate over all PlugName@PlugType in plugin directory, and try to open them |
287 for PlugDir in os.listdir(self.PlugPath()): |
333 for PlugDir in os.listdir(self.PlugPath()): |
288 if os.path.isdir(os.path.join(self.PlugPath(),PlugDir)) and \ |
334 if os.path.isdir(os.path.join(self.PlugPath(), PlugDir)) and \ |
289 PlugDir.count(NameTypeSeparator) == 1: |
335 PlugDir.count(NameTypeSeparator) == 1: |
290 try: |
336 try: |
291 self.PlugAddChild(*PlugDir.split[NameTypeSeparator]) |
337 self.PlugAddChild(*PlugDir.split(NameTypeSeparator)) |
292 except Exception, e: |
338 except Exception, e: |
293 print e |
339 print e |
294 |
340 |
|
341 def _GetClassFunction(name): |
|
342 def GetRootClass(): |
|
343 return getattr(__import__("plugins." + name), name).RootClass |
|
344 return GetRootClass |
|
345 |
295 class PluginsRoot(PlugTemplate): |
346 class PluginsRoot(PlugTemplate): |
296 |
347 |
297 # For root object, available Childs Types are modules of the plugin packages. |
348 # For root object, available Childs Types are modules of the plugin packages. |
298 PlugChildsTypes = [(name,lambda : getattr(__import__("plugins." + name), name).RootClass) for name in plugins.__all__] |
349 PlugChildsTypes = [(name, _GetClassFunction(name)) for name in plugins.__all__] |
299 |
350 |
300 XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> |
351 XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> |
301 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
352 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
302 <xsd:simpleType name="Win32Compiler"> |
353 <xsd:simpleType name="Win32Compiler"> |
303 <xsd:restriction base="xsd:string"> |
354 <xsd:restriction base="xsd:string"> |
312 <xsd:complexType> |
363 <xsd:complexType> |
313 <xsd:choice> |
364 <xsd:choice> |
314 <xsd:element name="Win32"> |
365 <xsd:element name="Win32"> |
315 <xsd:complexType> |
366 <xsd:complexType> |
316 <xsd:attribute name="ToolChain" type="ppx:Win32Compiler" use="required" default="MinGW"/> |
367 <xsd:attribute name="ToolChain" type="ppx:Win32Compiler" use="required" default="MinGW"/> |
317 <xsd:attribute name="Priority" type="xsd:integer" use="required" default="0"/> |
368 <xsd:attribute name="Priority" type="xsd:integer" use="required"/> |
318 </xsd:complexType> |
369 </xsd:complexType> |
319 </xsd:element> |
370 </xsd:element> |
320 <xsd:element name="Linux"> |
371 <xsd:element name="Linux"> |
321 <xsd:complexType> |
372 <xsd:complexType> |
322 <xsd:attribute name="Compiler" type="xsd:string" use="required" default="gcc"/> |
373 <xsd:attribute name="Compiler" type="xsd:string" use="required" default="gcc"/> |
323 <xsd:attribute name="Nice" type="xsd:integer" use="required" default="0"/> |
374 <xsd:attribute name="Nice" type="xsd:integer" use="required"/> |
324 </xsd:complexType> |
375 </xsd:complexType> |
325 </xsd:element> |
376 </xsd:element> |
326 <xsd:element name="Xenomai"> |
377 <xsd:element name="Xenomai"> |
327 <xsd:complexType> |
378 <xsd:complexType> |
328 <xsd:attribute name="xeno-config" type="xsd:string" use="required" default="/usr/xenomai/"/> |
379 <xsd:attribute name="xeno-config" type="xsd:string" use="required" default="/usr/xenomai/"/> |
329 <xsd:attribute name="Compiler" type="xsd:string" use="required" default="0"/> |
380 <xsd:attribute name="Compiler" type="xsd:string" use="required"/> |
330 <xsd:attribute name="Priority" type="xsd:integer" use="required" default="0"/> |
381 <xsd:attribute name="Priority" type="xsd:integer" use="required"/> |
331 </xsd:complexType> |
382 </xsd:complexType> |
332 </xsd:element> |
383 </xsd:element> |
333 <xsd:element name="RTAI"> |
384 <xsd:element name="RTAI"> |
334 <xsd:complexType> |
385 <xsd:complexType> |
335 <xsd:attribute name="xeno-config" type="xsd:string" use="required" default="0"/> |
386 <xsd:attribute name="xeno-config" type="xsd:string" use="required"/> |
336 <xsd:attribute name="Compiler" type="xsd:string" use="required" default="0"/> |
387 <xsd:attribute name="Compiler" type="xsd:string" use="required"/> |
337 <xsd:attribute name="Priority" type="xsd:integer" use="required" default="0"/> |
388 <xsd:attribute name="Priority" type="xsd:integer" use="required"/> |
338 </xsd:complexType> |
389 </xsd:complexType> |
339 </xsd:element> |
390 </xsd:element> |
340 <xsd:element name="Library"> |
391 <xsd:element name="Library"> |
341 <xsd:complexType> |
392 <xsd:complexType> |
342 <xsd:attribute name="Dynamic" type="xsd:boolean" default="true"/> |
393 <xsd:attribute name="Dynamic" type="xsd:boolean" use="required" default="true"/> |
343 <xsd:attribute name="Compiler" type="xsd:string" use="required" default="0"/> |
394 <xsd:attribute name="Compiler" type="xsd:string" use="required"/> |
344 </xsd:complexType> |
395 </xsd:complexType> |
345 </xsd:element> |
396 </xsd:element> |
346 </xsd:choice> |
397 </xsd:choice> |
347 </xsd:complexType> |
398 </xsd:complexType> |
348 </xsd:element> |
399 </xsd:element> |
349 </xsd:complexType> |
400 </xsd:complexType> |
350 </xsd:element> |
401 </xsd:element> |
351 </xsd:schema> |
402 </xsd:schema> |
352 """ |
403 """ |
353 |
404 |
354 def __init__(self, ProjectPath): |
405 def __init__(self): |
|
406 PlugTemplate.__init__(self) |
355 # self is the parent |
407 # self is the parent |
356 self.PlugParent = None |
408 self.PlugParent = None |
357 # Keep track of the plugin type name |
409 # Keep track of the plugin type name |
358 self.PlugType = "Beremiz" |
410 self.PlugType = "Beremiz" |
359 # Keep track of the root plugin (i.e. project path) |
411 |
360 self.ProjectPath = ProjectPath |
412 self.ProjectPath = "" |
|
413 self.PLCManager = None |
|
414 |
|
415 def HasProjectOpened(self): |
|
416 """ |
|
417 Return if a project is actually opened |
|
418 """ |
|
419 return self.ProjectPath != "" |
|
420 |
|
421 def GetProjectPath(self): |
|
422 return self.ProjectPath |
|
423 |
|
424 def GetTargetTypes(self): |
|
425 return self.BeremizRoot.TargetType.getChoices().keys() |
|
426 |
|
427 def ChangeTargetType(self, target_type): |
|
428 self.BeremizRoot.TargetType.addContent(target_type) |
|
429 |
|
430 def GetTargetAttributes(self): |
|
431 content = self.BeremizRoot.TargetType.getContent() |
|
432 if content: |
|
433 return content["value"].getElementAttributes() |
|
434 else: |
|
435 return [] |
|
436 |
|
437 def SetTargetAttribute(self, name, value): |
|
438 content = self.BeremizRoot.TargetType.getContent() |
|
439 if content: |
|
440 attr = getattr(content["value"], name, None) |
|
441 if isinstance(attr, types.ClassType): |
|
442 attr.SetValue(value) |
|
443 else: |
|
444 setattr(content["value"], name, value) |
|
445 |
|
446 def GetTargetType(self): |
|
447 content = self.BeremizRoot.TargetType.getContent() |
|
448 if content: |
|
449 return content["name"] |
|
450 else: |
|
451 return "" |
|
452 |
|
453 def NewProject(self, ProjectPath, PLCParams): |
|
454 """ |
|
455 Create a new project in an empty folder |
|
456 @param ProjectPath: path of the folder where project have to be created |
|
457 @param PLCParams: properties of the PLCOpen program created |
|
458 """ |
|
459 # Verify that choosen folder is empty |
|
460 if not os.path.isdir(ProjectPath) or len(os.listdir(ProjectPath)) > 0: |
|
461 return "Folder choosen isn't empty. You can't use it for a new project!" |
|
462 # Create Controler for PLCOpen program |
|
463 self.PLCManager = PLCControler() |
|
464 self.PLCManager.CreateNewProject(PLCParams.pop("projectName")) |
|
465 self.PLCManager.SetProjectProperties(properties = PLCParams) |
361 # Change XSD into class members |
466 # Change XSD into class members |
362 self._AddParamsMembers() |
467 self._AddParamsMembers() |
363 self.PluggedChilds = {} |
468 self.PluggedChilds = {} |
364 # No IEC channel, name, etc... |
469 # No IEC channel, name, etc... |
365 self.MandatoryParams = [] |
470 self.MandatoryParams = [] |
|
471 # Keep track of the root plugin (i.e. project path) |
|
472 self.ProjectPath = ProjectPath |
|
473 self.BaseParams.setName(os.path.split(ProjectPath)[1]) |
|
474 return None |
|
475 |
|
476 def LoadProject(self, ProjectPath): |
|
477 """ |
|
478 Load a project contained in a folder |
|
479 @param ProjectPath: path of the project folder |
|
480 """ |
|
481 # Verify that project contains a PLCOpen program |
|
482 plc_file = os.path.join(ProjectPath, "plc.xml") |
|
483 if not os.path.isfile(plc_file): |
|
484 return "Folder choosen doesn't contain a program. It's not a valid project!" |
|
485 # Create Controler for PLCOpen program |
|
486 self.PLCManager = PLCControler() |
|
487 # Load PLCOpen file |
|
488 result = self.PLCManager.OpenXMLFile(plc_file) |
|
489 if result: |
|
490 return result |
|
491 # Change XSD into class members |
|
492 self._AddParamsMembers() |
|
493 self.PluggedChilds = {} |
|
494 # No IEC channel, name, etc... |
|
495 self.MandatoryParams = None |
|
496 # Keep track of the root plugin (i.e. project path) |
|
497 self.ProjectPath = ProjectPath |
366 # If dir have already be made, and file exist |
498 # If dir have already be made, and file exist |
367 if os.path.isdir(_self.PlugPath(PlugName)) and os.path.isfile(_self.PluginXmlFilePath(PlugName)): |
499 if os.path.isdir(self.PlugPath()) and os.path.isfile(self.PluginXmlFilePath()): |
368 #Load the plugin.xml file into parameters members |
500 #Load the plugin.xml file into parameters members |
369 _self.LoadXMLParams() |
501 result = self.LoadXMLParams(test = False) |
|
502 if result: |
|
503 return result |
370 #Load and init all the childs |
504 #Load and init all the childs |
371 _self.LoadChilds() |
505 self.LoadChilds() |
372 |
506 self.BaseParams.setName(os.path.split(ProjectPath)[1]) |
373 def PlugPath(self,PlugName=None): |
507 return None |
|
508 |
|
509 def SaveProject(self): |
|
510 if not self.PLCManager.SaveXMLFile(): |
|
511 self.PLCManager.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml')) |
|
512 self.PlugRequestSave() |
|
513 |
|
514 def PlugPath(self, PlugName=None): |
374 return self.ProjectPath |
515 return self.ProjectPath |
375 |
516 |
|
517 def PluginBaseXmlFilePath(self, PlugName=None): |
|
518 return None |
|
519 |
376 def PluginXmlFilePath(self, PlugName=None): |
520 def PluginXmlFilePath(self, PlugName=None): |
377 return os.path.join(self.PlugPath(PlugName), "beremiz.xml") |
521 return os.path.join(self.PlugPath(PlugName), "beremiz.xml") |
378 |
|
379 |
|