--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/objdictgen/nodemanager.py Wed May 10 16:59:40 2006 +0200
@@ -0,0 +1,1237 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of CanFestival, a library implementing CanOpen Stack.
+#
+#Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+#Lesser General Public License for more details.
+#
+#You should have received a copy of the GNU Lesser General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from gnosis.xml.pickle import *
+from gnosis.xml.pickle.util import setParanoia
+setParanoia(0)
+
+from node import *
+import xml_in, gen_cfile
+
+from types import *
+import os, re
+
+UndoBufferLength = 20
+
+type_model = re.compile('([\_A-Z]*)([0-9]*)')
+range_model = re.compile('([\_A-Z]*)([0-9]*)\[([\-0-9]*)-([\-0-9]*)\]')
+name_model = re.compile('(.*)\[(.*)\]')
+
+def IsOfType(object, typedef):
+ return type(object) == typedef
+
+#-------------------------------------------------------------------------------
+# Formating Name of an Entry
+#-------------------------------------------------------------------------------
+
+"""
+Format the text given with the index and subindex defined
+"""
+
+def StringFormat(text, idx, sub):
+ result = name_model.match(text)
+ if result:
+ format = result.groups()
+ return format[0]%eval(format[1])
+ else:
+ return text
+
+#-------------------------------------------------------------------------------
+# Search in a Mapping Dictionary
+#-------------------------------------------------------------------------------
+
+"""
+Return the index of the informations in the Object Dictionary in case of identical
+indexes
+"""
+def FindIndex(index, mappingdictionary):
+ if index in mappingdictionary:
+ return index
+ else:
+ listpluri = [idx for idx in mappingdictionary.keys() if mappingdictionary[idx]["struct"] & OD_IdenticalIndexes]
+ listpluri.sort()
+ for idx in listpluri:
+ nb_max = mappingdictionary[idx]["nbmax"]
+ incr = mappingdictionary[idx]["incr"]
+ if idx < index < idx + incr * nb_max and (index - idx)%incr == 0:
+ return idx
+ return None
+
+"""
+Return the index of the typename given by searching in mappingdictionary
+"""
+def FindTypeIndex(typename, mappingdictionary):
+ testdic = {}
+ for index, values in mappingdictionary.iteritems():
+ if index < 0x1000:
+ testdic[values["name"]] = index
+ if typename in testdic:
+ return testdic[typename]
+ return None
+
+"""
+Return the name of the type by searching in mappingdictionary
+"""
+def FindTypeName(typeindex, mappingdictionary):
+ if typeindex < 0x1000 and typeindex in mappingdictionary:
+ return mappingdictionary[typeindex]["name"]
+ return None
+
+"""
+Return the default value of the type by searching in mappingdictionary
+"""
+def FindTypeDefaultValue(typeindex, mappingdictionary):
+ if typeindex < 0x1000 and typeindex in mappingdictionary:
+ return mappingdictionary[typeindex]["default"]
+ return None
+
+"""
+Return the list of types defined in mappingdictionary
+"""
+def FindTypeList(mappingdictionary):
+ list = []
+ for index in mappingdictionary.keys():
+ if index < 0x1000:
+ list.append((index, mappingdictionary[index]["name"]))
+ return list
+
+"""
+Return the name of an entry by searching in mappingdictionary
+"""
+def FindEntryName(index, mappingdictionary):
+ base_index = FindIndex(index, mappingdictionary)
+ if base_index:
+ infos = mappingdictionary[base_index]
+ if infos["struct"] & OD_IdenticalIndexes:
+ return StringFormat(infos["name"], (index - base_index) / infos["incr"] + 1, 0)
+ else:
+ return infos["name"]
+ return None
+
+"""
+Return the informations of one entry by searching in mappingdictionary
+"""
+def FindEntryInfos(index, mappingdictionary):
+ base_index = FindIndex(index, mappingdictionary)
+ if base_index:
+ copy = mappingdictionary[base_index].copy()
+ if copy["struct"] & OD_IdenticalIndexes:
+ copy["name"] = StringFormat(copy["name"], (index - base_index) / copy["incr"] + 1, 0)
+ copy.pop("values")
+ return copy
+ return None
+
+"""
+Return the informations of one subentry of an entry by searching in mappingdictionary
+"""
+def FindSubentryInfos(index, subIndex, mappingdictionary):
+ base_index = FindIndex(index, mappingdictionary)
+ if base_index:
+ struct = mappingdictionary[base_index]["struct"]
+ if struct & OD_Subindex:
+ if struct & OD_IdenticalSubindexes:
+ if struct & OD_IdenticalIndexes:
+ incr = mappingdictionary[base_index]["incr"]
+ else:
+ incr = 1
+ if subIndex == 0:
+ return mappingdictionary[base_index]["values"][0].copy()
+ elif 0 < subIndex <= mappingdictionary[base_index]["values"][1]["nbmax"]:
+ copy = mappingdictionary[base_index]["values"][1].copy()
+ copy["name"] = StringFormat(copy["name"], (index - base_index) / incr + 1, subIndex)
+ return copy
+ elif struct & OD_MultipleSubindexes and 0 <= subIndex < len(mappingdictionary[base_index]["values"]):
+ return mappingdictionary[base_index]["values"][subIndex].copy()
+ elif subIndex == 0:
+ return mappingdictionary[base_index]["values"][0].copy()
+ return None
+
+"""
+Return the list of variables that can be mapped defined in mappingdictionary
+"""
+def FindMapVariableList(mappingdictionary, Manager):
+ list = []
+ for index in mappingdictionary.iterkeys():
+ if Manager.IsCurrentEntry(index):
+ for subIndex, values in enumerate(mappingdictionary[index]["values"]):
+ if mappingdictionary[index]["values"][subIndex]["pdo"]:
+ infos = Manager.GetEntryInfos(mappingdictionary[index]["values"][subIndex]["type"])
+ if mappingdictionary[index]["struct"] & OD_IdenticalSubindexes:
+ values = Manager.GetCurrentEntry(index)
+ for i in xrange(len(values)):
+ list.append((index, i + 1, infos["size"], StringFormat(mappingdictionary[index]["values"][subIndex]["name"],1,i)))
+ else:
+ list.append((index, subIndex, infos["size"], mappingdictionary[index]["values"][subIndex]["name"]))
+ return list
+
+"""
+Return the list of mandatory indexes defined in mappingdictionary
+"""
+def FindMandatoryIndexes(mappingdictionary):
+ list = []
+ for index in mappingdictionary.iterkeys():
+ if index >= 0x1000 and mappingdictionary[index]["need"]:
+ list.append(index)
+ return list
+
+
+"""
+Class implementing a buffer of changes made on the current editing Object Dictionary
+"""
+
+class UndoBuffer:
+
+ """
+ Constructor initialising buffer
+ """
+ def __init__(self, currentstate, issaved = False):
+ self.Buffer = []
+ self.CurrentIndex = -1
+ self.MinIndex = -1
+ self.MaxIndex = -1
+ # if current state is defined
+ if currentstate:
+ self.CurrentIndex = 0
+ self.MinIndex = 0
+ self.MaxIndex = 0
+ # Initialising buffer with currentstate at the first place
+ for i in xrange(UndoBufferLength):
+ if i == 0:
+ self.Buffer.append(currentstate)
+ else:
+ self.Buffer.append(None)
+ # Initialising index of state saved
+ if issaved:
+ self.LastSave = 0
+ else:
+ self.LastSave = -1
+
+ """
+ Add a new state in buffer
+ """
+ def Buffering(self, currentstate):
+ self.CurrentIndex = (self.CurrentIndex + 1) % UndoBufferLength
+ self.Buffer[self.CurrentIndex] = currentstate
+ # Actualising buffer limits
+ self.MaxIndex = self.CurrentIndex
+ if self.MinIndex == self.CurrentIndex:
+ # If the removed state was the state saved, there is no state saved in the buffer
+ if self.LastSave == self.MinIndex:
+ self.LastSave = -1
+ self.MinIndex = (self.MinIndex + 1) % UndoBufferLength
+ self.MinIndex = max(self.MinIndex, 0)
+
+ """
+ Return current state of buffer
+ """
+ def Current(self):
+ return self.Buffer[self.CurrentIndex]
+
+ """
+ Change current state to previous in buffer and return new current state
+ """
+ def Previous(self):
+ if self.CurrentIndex != self.MinIndex:
+ self.CurrentIndex = (self.CurrentIndex - 1) % UndoBufferLength
+ return self.Buffer[self.CurrentIndex]
+ return None
+
+ """
+ Change current state to next in buffer and return new current state
+ """
+ def Next(self):
+ if self.CurrentIndex != self.MaxIndex:
+ self.CurrentIndex = (self.CurrentIndex + 1) % UndoBufferLength
+ return self.Buffer[self.CurrentIndex]
+ return None
+
+ """
+ Return True if current state is the first in buffer
+ """
+ def IsFirst(self):
+ return self.CurrentIndex == self.MinIndex
+
+ """
+ Return True if current state is the last in buffer
+ """
+ def IsLast(self):
+ return self.CurrentIndex == self.MaxIndex
+
+ """
+ Note that current state is saved
+ """
+ def CurrentSaved(self):
+ self.LastSave = self.CurrentIndex
+
+ """
+ Return True if current state is saved
+ """
+ def IsCurrentSaved(self):
+ return self.LastSave == self.CurrentIndex
+
+
+
+"""
+Class which control the operations made on the node and answer to view requests
+"""
+
+class NodeManager:
+
+ """
+ Constructor
+ """
+ def __init__(self):
+ self.LastNewIndex = 0
+ self.FilePaths = []
+ self.FileNames = []
+ self.NodeIndex = -1
+ self.CurrentNode = None
+ self.UndoBuffers = []
+
+#-------------------------------------------------------------------------------
+# Type and Map Variable Lists
+#-------------------------------------------------------------------------------
+
+ """
+ Generate the list of types defined for the current node
+ """
+ def GenerateTypeList(self):
+ self.TypeList = ""
+ self.TypeTranslation = {}
+ list = self.GetTypeList()
+ sep = ""
+ for index, name in list:
+ self.TypeList += "%s%s"%(sep,name)
+ self.TypeTranslation[name] = index
+ sep = ","
+
+ """
+ Generate the list of variables that can be mapped for the current node
+ """
+ def GenerateMapList(self):
+ self.MapList = "None"
+ self.NameTranslation = {"None" : "00000000"}
+ self.MapTranslation = {"00000000" : "None"}
+ list = self.GetMapVariableList()
+ for index, subIndex, size, name in list:
+ self.MapList += ",%s"%name
+ map = "%04X%02X%02X"%(index,subIndex,size)
+ self.NameTranslation[name] = map
+ self.MapTranslation[map] = name
+
+ """
+ Return the list of types defined for the current node
+ """
+ def GetCurrentTypeList(self):
+ return self.TypeList
+
+ """
+ Return the list of variables that can be mapped for the current node
+ """
+ def GetCurrentMapList(self):
+ return self.MapList
+
+#-------------------------------------------------------------------------------
+# Create Load and Save Functions
+#-------------------------------------------------------------------------------
+
+ """
+ Create a new node and add a new buffer for storing it
+ """
+ def CreateNewNode(self, name, id, type, profile, filepath, NMT, options):
+ # Create a new node
+ node = Node()
+ # Try to load profile given
+ result = self.LoadProfile(profile, filepath, node)
+ if not IsOfType(result, StringType):
+ # if success, initialising node
+ self.CurrentNode = node
+ self.CurrentNode.SetNodeName(name)
+ self.CurrentNode.SetNodeID(id)
+ self.CurrentNode.SetNodeType(type)
+ AddIndexList = self.GetMandatoryIndexes()
+ if NMT == "NodeGuarding":
+ AddIndexList.extend([0x100C, 0x100D])
+ elif NMT == "Heartbeat":
+ AddIndexList.append(0x1017)
+ for option in options:
+ if option == "DS302":
+ # Charging DS-302 profile if choosen by user
+ if os.path.isfile("config/DS-302.prf"):
+ try:
+ Mapping = {}
+ AddMenuEntries = []
+ execfile("config/DS-302.prf")
+ self.CurrentNode.SetDS302Profile(Mapping)
+ self.CurrentNode.ExtendSpecificMenu(AddMenuEntries)
+ except:
+ return "Problem with DS-302! Syntax Error."
+ else:
+ return "Couldn't find DS-302 in 'config' folder!"
+ elif option == "GenSYNC":
+ AddIndexList.extend([0x1005, 0x1006])
+ elif option == "Emergency":
+ AddIndexList.append(0x1014)
+ elif option == "SaveConfig":
+ AddIndexList.extend([0x1010, 0x1011, 0x1020])
+ elif option == "StoreEDS":
+ AddIndexList.extend([0x1021, 0x1022])
+ # Add a new buffer
+ self.AddNodeBuffer()
+ self.SetCurrentFilePath("")
+ # Add Mandatory indexes
+ self.ManageEntriesOfCurrent(AddIndexList, [])
+ # Regenerate lists
+ self.GenerateTypeList()
+ self.GenerateMapList()
+ return True
+ else:
+ return result
+
+ """
+ Load a profile in node
+ """
+ def LoadProfile(self, profile, filepath, node):
+ if profile != "None":
+ # Try to charge the profile given
+ try:
+ execfile(filepath)
+ node.SetProfileName(profile)
+ node.SetProfile(Mapping)
+ node.SetSpecificMenu(AddMenuEntries)
+ return True
+ except:
+ return "Bad OD Profile file!\nSyntax Error."
+ else:
+ # Default profile
+ node.SetProfileName("None")
+ node.SetProfile({})
+ node.SetSpecificMenu([])
+ return True
+
+ """
+ Open a file and store it in a new buffer
+ """
+ def OpenFileInCurrent(self, filepath):
+ # Open and load file
+ file = open(filepath, "r")
+ node = load(file)
+ file.close()
+ self.CurrentNode = node
+ # Add a new buffer and defining current state
+ self.AddNodeBuffer(self.CurrentNode.Copy(), True)
+ self.SetCurrentFilePath(filepath)
+ # Regenerate lists
+ self.GenerateTypeList()
+ self.GenerateMapList()
+ return True
+
+ """
+ Save current node in a file
+ """
+ def SaveCurrentInFile(self, filepath = None):
+ # if no filepath given, verify if current node has a filepath defined
+ if not filepath:
+ filepath = self.GetCurrentFilePath()
+ if filepath == "":
+ return False
+ # Save node in file
+ file = open(filepath, "w")
+ dump(self.CurrentNode, file)
+ file.close()
+ self.SetCurrentFilePath(filepath)
+ # Update saved state in buffer
+ self.UndoBuffers[self.NodeIndex].CurrentSaved()
+ return True
+
+ """
+ Close current state
+ """
+ def CloseCurrent(self, ignore = False):
+ # Verify if it's not forced that the current node is saved before closing it
+ if self.UndoBuffers[self.NodeIndex].IsCurrentSaved() or ignore:
+ self.RemoveNodeBuffer(self.NodeIndex)
+ return True
+ return False
+
+ """
+ Import a xml file and store it in a new buffer if no node edited
+ """
+ def ImportCurrentFromFile(self, filepath):
+ # Generate node from definition in a xml file
+ node = xml_in.GenerateNode(filepath, self)
+ if node:
+ self.CurrentNode = node
+ self.GenerateTypeList()
+ self.GenerateMapList()
+ if len(self.UndoBuffers) == 0:
+ self.AddNodeBuffer()
+ self.SetCurrentFilePath("")
+ self.BufferCurrentNode()
+ return result
+
+ """
+ Build the C definition of Object Dictionary for current node
+ """
+ def ExportCurrentToFile(self, filepath):
+ return gen_cfile.GenerateFile(filepath, self)
+
+#-------------------------------------------------------------------------------
+# Add Entries to Current Functions
+#-------------------------------------------------------------------------------
+
+ """
+ Add the specified number of subentry for the given entry. Verify that total
+ number of subentry (except 0) doesn't exceed nbmax defined
+ """
+ def AddSubentriesToCurrent(self, index, number):
+ # Informations about entry
+ length = self.CurrentNode.GetEntry(index, 0)
+ infos = self.GetEntryInfos(index)
+ subentry_infos = self.GetSubentryInfos(index, 1)
+ # Get default value for subindex
+ if "default" in subentry_infos:
+ default = subentry_infos["default"]
+ else:
+ default = self.GetTypeDefaultValue(subentry_infos["type"])
+ # First case entry is record
+ if infos["struct"] & OD_IdenticalSubindexes:
+ for i in xrange(1, min(number,subentry_infos["nbmax"]-length) + 1):
+ self.CurrentNode.AddEntry(index, length + i, default)
+ self.BufferCurrentNode()
+ # Second case entry is array, only possible for manufacturer specific
+ elif infos["struct"] & OD_MultipleSubindexes and 0x2000 <= index <= 0x5FFF:
+ values = {"name" : "Undefined", "type" : 5, "access" : "rw", "pdo" : True}
+ for i in xrange(1, min(number,0xFE-length) + 1):
+ self.CurrentNode.AddMappingEntry(index, length + i, values = values.copy())
+ self.CurrentNode.AddEntry(index, length + i, 0)
+ self.BufferCurrentNode()
+
+ """
+ Remove the specified number of subentry for the given entry. Verify that total
+ number of subentry (except 0) isn't less than 1
+ """
+ def RemoveSubentriesFromCurrent(self, index, number):
+ # Informations about entry
+ infos = self.GetEntryInfos(index)
+ length = self.CurrentNode.GetEntry(index, 0)
+ # Entry is a record, or is an array of manufacturer specific
+ if infos["struct"] & OD_IdenticalSubindexes or 0x2000 <= index <= 0x5FFF and infos["struct"] & OD_IdenticalSubindexes:
+ for i in xrange(min(number, length - 1)):
+ self.RemoveCurrentVariable(index, length - i)
+ self.BufferCurrentNode()
+
+ """
+ Add a SDO Server to current node
+ """
+ def AddSDOServerToCurrent(self):
+ # An SDO Server is already defined at index 0x1200
+ if self.CurrentNode.IsEntry(0x1200):
+ indexlist = [self.GetLineFromIndex(0x1201)]
+ if None not in indexlist:
+ self.ManageEntriesOfCurrent(indexlist, [])
+ # Add an SDO Server at index 0x1200
+ else:
+ self.ManageEntriesOfCurrent([0x1200], [])
+
+ """
+ Add a SDO Server to current node
+ """
+ def AddSDOClientToCurrent(self):
+ indexlist = [self.GetLineFromIndex(0x1280)]
+ if None not in indexlist:
+ self.ManageEntriesOfCurrent(indexlist, [])
+
+ """
+ Add a Transmit PDO to current node
+ """
+ def AddPDOTransmitToCurrent(self):
+ indexlist = [self.GetLineFromIndex(0x1800),self.GetLineFromIndex(0x1A00)]
+ if None not in indexlist:
+ self.ManageEntriesOfCurrent(indexlist, [])
+
+ """
+ Add a Receive PDO to current node
+ """
+ def AddPDOReceiveToCurrent(self):
+ indexlist = [self.GetLineFromIndex(0x1400),self.GetLineFromIndex(0x1600)]
+ if None not in indexlist:
+ self.ManageEntriesOfCurrent(indexlist, [])
+
+ """
+ Add a list of entries defined in profile for menu item selected to current node
+ """
+ def AddSpecificEntryToCurrent(self, menuitem):
+ indexlist = []
+ for menu, indexes in self.CurrentNode.GetSpecificMenu():
+ if menuitem == menu:
+ for index in indexes:
+ indexlist.append(self.GetLineFromIndex(index))
+ if None not in indexlist:
+ self.ManageEntriesOfCurrent(indexlist, [])
+
+ """
+ Search the first index available for a pluri entry from base_index
+ """
+ def GetLineFromIndex(self, base_index):
+ found = False
+ index = base_index
+ infos = self.GetEntryInfos(base_index)
+ while index < base_index + infos["incr"]*infos["nbmax"] and not found:
+ if not self.CurrentNode.IsEntry(index):
+ found = True
+ else:
+ index += infos["incr"]
+ if found:
+ return index
+ return None
+
+ """
+ Add entries specified in addinglist and remove entries specified in removinglist
+ """
+ def ManageEntriesOfCurrent(self, addinglist, removinglist):
+ # Add all the entries in addinglist
+ for index in addinglist:
+ infos = self.GetEntryInfos(index)
+ if infos["struct"] & OD_MultipleSubindexes:
+ # First case entry is a record
+ if infos["struct"] & OD_IdenticalSubindexes:
+ subentry_infos = self.GetSubentryInfos(index, 1)
+ if "default" in subentry_infos:
+ default = subentry_infos["default"]
+ else:
+ default = self.GetTypeDefaultValue(subentry_infos["type"])
+ self.CurrentNode.AddEntry(index, 1, default)
+ # Second case entry is a record
+ else:
+ i = 1
+ subentry_infos = self.GetSubentryInfos(index, i)
+ while subentry_infos:
+ if "default" in subentry_infos:
+ default = subentry_infos["default"]
+ else:
+ default = self.GetTypeDefaultValue(subentry_infos["type"])
+ self.CurrentNode.AddEntry(index, i, default)
+ i += 1
+ subentry_infos = self.GetSubentryInfos(index, i)
+ # Third case entry is a record
+ else:
+ subentry_infos = self.GetSubentryInfos(index, 0)
+ if "default" in subentry_infos:
+ default = subentry_infos["default"]
+ else:
+ default = self.GetTypeDefaultValue(subentry_infos["type"])
+ self.CurrentNode.AddEntry(index, 0, default)
+ # Remove all the entries in removinglist
+ for index in removinglist:
+ self.RemoveCurrentVariable(index)
+ self.BufferCurrentNode()
+
+ """
+ Remove an entry from current node. Analize the index to perform the correct
+ method
+ """
+ def RemoveCurrentVariable(self, index, subIndex = None):
+ Mappings = self.CurrentNode.GetMappings()
+ if index < 0x1000 and subIndex == None:
+ type = self.CurrentNode.GetEntry(index, 1)
+ for i in Mappings[-1]:
+ for value in Mappings[-1][i]["values"]:
+ if value["type"] == index:
+ value["type"] = type
+ self.CurrentNode.RemoveMappingEntry(index)
+ self.CurrentNode.RemoveEntry(index)
+ elif index == 0x1200 and subIndex == None:
+ self.CurrentNode.RemoveEntry(0x1200)
+ elif 0x1201 <= index <= 0x127F and subIndex == None:
+ self.CurrentNode.RemoveLine(index, 0x127F)
+ elif 0x1280 <= index <= 0x12FF and subIndex == None:
+ self.CurrentNode.RemoveLine(index, 0x12FF)
+ elif 0x1400 <= index <= 0x15FF or 0x1600 <= index <= 0x17FF and subIndex == None:
+ if 0x1600 <= index <= 0x17FF and subIndex == None:
+ index -= 0x200
+ self.CurrentNode.RemoveLine(index, 0x15FF)
+ self.CurrentNode.RemoveLine(index + 0x200, 0x17FF)
+ elif 0x1800 <= index <= 0x19FF or 0x1A00 <= index <= 0x1BFF and subIndex == None:
+ if 0x1A00 <= index <= 0x1BFF:
+ index -= 0x200
+ self.CurrentNode.RemoveLine(index, 0x19FF)
+ self.CurrentNode.RemoveLine(index + 0x200, 0x1BFF)
+ else:
+ found = False
+ for menu,list in self.CurrentNode.GetSpecificMenu():
+ for i in list:
+ iinfos = self.GetEntryInfos(i)
+ indexes = [i + incr * iinfos["incr"] for incr in xrange(iinfos["nbmax"])]
+ if index in indexes:
+ found = True
+ diff = index - i
+ for j in list:
+ jinfos = self.GetEntryInfos(j)
+ self.CurrentNode.RemoveLine(j + diff, j + jinfos["incr"]*jinfos["nbmax"], jinfos["incr"])
+ self.CurrentNode.RemoveMapVariable(index, subIndex)
+ if not found:
+ infos = self.GetEntryInfos(index)
+ if not infos["need"]:
+ self.CurrentNode.RemoveEntry(index, subIndex)
+ if index in Mappings[-1]:
+ self.CurrentNode.RemoveMappingEntry(index, subIndex)
+ self.GenerateMapList()
+
+ def AddMapVariableToCurrent(self, index, name, struct, number):
+ if 0x2000 <= index <= 0x5FFF:
+ if not self.CurrentNode.IsEntry(index):
+ self.CurrentNode.AddMappingEntry(index, name = name, struct = struct)
+ if struct == var:
+ values = {"name" : name, "type" : 5, "access" : "rw", "pdo" : True}
+ self.CurrentNode.AddMappingEntry(index, 0, values = values)
+ self.CurrentNode.AddEntry(index, 0, 0)
+ else:
+ values = {"name" : "Number of Entries", "type" : 2, "access" : "ro", "pdo" : False}
+ self.CurrentNode.AddMappingEntry(index, 0, values = values)
+ if struct == rec:
+ values = {"name" : name + " %d[(sub)]", "type" : 5, "access" : "rw", "pdo" : True, "nbmax" : 0xFE}
+ self.CurrentNode.AddMappingEntry(index, 1, values = values)
+ for i in xrange(number):
+ self.CurrentNode.AddEntry(index, i + 1, 0)
+ else:
+ for i in xrange(number):
+ values = {"name" : "Undefined", "type" : 5, "access" : "rw", "pdo" : True}
+ self.CurrentNode.AddMappingEntry(index, i + 1, values = values)
+ self.CurrentNode.AddEntry(index, i + 1, 0)
+ self.GenerateMapList()
+ self.BufferCurrentNode()
+ return None
+ else:
+ return "Index 0x%04X already defined!"%index
+ else:
+ return "Index 0x%04X isn't a valid index for Map Variable!"%index
+
+ def AddUserTypeToCurrent(self, type, min, max, length):
+ index = 0xA0
+ while index < 0x100 and self.CurrentNode.IsEntry(index):
+ index += 1
+ if index < 0x100:
+ customisabletypes = self.GetCustomisableTypes()
+ name, valuetype = customisabletypes[type]
+ size = self.GetEntryInfos(type)["size"]
+ default = self.GetTypeDefaultValue(type)
+ if valuetype == 0:
+ self.CurrentNode.AddMappingEntry(index, name = "%s[%d-%d]"%(name, min, max), struct = 3, size = size, default = default)
+ self.CurrentNode.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})
+ self.CurrentNode.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False})
+ self.CurrentNode.AddMappingEntry(index, 2, values = {"name" : "Minimum Value", "type" : type, "access" : "ro", "pdo" : False})
+ self.CurrentNode.AddMappingEntry(index, 3, values = {"name" : "Maximum Value", "type" : type, "access" : "ro", "pdo" : False})
+ self.CurrentNode.AddEntry(index, 1, type)
+ self.CurrentNode.AddEntry(index, 2, min)
+ self.CurrentNode.AddEntry(index, 3, max)
+ elif valuetype == 1:
+ self.CurrentNode.AddMappingEntry(index, name = "%s%d"%(name, length), struct = 3, size = length * size, default = default)
+ self.CurrentNode.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})
+ self.CurrentNode.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False})
+ self.CurrentNode.AddMappingEntry(index, 2, values = {"name" : "Length", "type" : 0x02, "access" : "ro", "pdo" : False})
+ self.CurrentNode.AddEntry(index, 1, type)
+ self.CurrentNode.AddEntry(index, 2, length)
+ self.GenerateTypeList()
+ self.BufferCurrentNode()
+ return None
+ else:
+ return "Too many User Types have already been defined!"
+
+#-------------------------------------------------------------------------------
+# Modify Entry and Mapping Functions
+#-------------------------------------------------------------------------------
+
+ def SetCurrentEntryCallbacks(self, index, value):
+ if self.CurrentNode and self.CurrentNode.IsEntry(index):
+ entry_infos = self.GetEntryInfos(index)
+ if "callback" not in entry_infos:
+ self.CurrentNode.SetParamsEntry(index, None, callback = value)
+ self.BufferCurrentNode()
+
+ def SetCurrentEntry(self, index, subIndex, value, name, editor):
+ if self.CurrentNode and self.CurrentNode.IsEntry(index):
+ if name == "value":
+ if editor == "map":
+ value = eval("0x%s"%self.NameTranslation[value])
+ self.CurrentNode.SetEntry(index, subIndex, value)
+ elif editor == "bool":
+ value = value == "True"
+ self.CurrentNode.SetEntry(index, subIndex, value)
+ else:
+ subentry_infos = self.GetSubentryInfos(index, subIndex)
+ dic = {}
+ for typeindex, typevalue in CustomisableTypes:
+ dic[typeindex] = typevalue
+ if dic[subentry_infos["type"]] == 0:
+ try:
+ value = eval(value, {})
+ self.CurrentNode.SetEntry(index, subIndex, value)
+ except:
+ pass
+ else:
+ self.CurrentNode.SetEntry(index, subIndex, value)
+ elif name in ["comment", "save"]:
+ if editor == "option":
+ value = value == "Yes"
+ if name == "save":
+ self.CurrentNode.SetParamsEntry(index, subIndex, save = value)
+ elif name == "comment":
+ self.CurrentNode.SetParamsEntry(index, subIndex, comment = value)
+ else:
+ if editor == "type":
+ value = self.TypeTranslation[value]
+ elif editor == "access":
+ dic = {}
+ for abbrev,access in AccessType.iteritems():
+ dic[access] = abbrev
+ value = dic[value]
+ self.CurrentNode.SetMappingEntry(index, subIndex, values = {name : value})
+ if name == "name":
+ self.GenerateMapList()
+ self.BufferCurrentNode()
+
+ def SetCurrentEntryName(self, index, name):
+ self.CurrentNode.SetMappingEntry(index, name=name)
+ self.BufferCurrentNode()
+
+ def SetCurrentUserType(self, index, type, min, max, length):
+ customisabletypes = self.GetCustomisableTypes()
+ values, valuetype = self.GetCustomisedTypeValues(index)
+ name, new_valuetype = customisabletypes[type]
+ size = self.GetEntryInfos(type)["size"]
+ default = self.GetTypeDefaultValue(type)
+ if new_valuetype == 0:
+ self.CurrentNode.SetMappingEntry(index, name = "%s[%d-%d]"%(name, min, max), struct = 3, size = size, default = default)
+ if valuetype == 1:
+ self.CurrentNode.SetMappingEntry(index, 2, values = {"name" : "Minimum Value", "type" : type, "access" : "ro", "pdo" : False})
+ self.CurrentNode.AddMappingEntry(index, 3, values = {"name" : "Maximum Value", "type" : type, "access" : "ro", "pdo" : False})
+ self.CurrentNode.SetEntry(index, 1, type)
+ self.CurrentNode.SetEntry(index, 2, min)
+ if valuetype == 1:
+ self.CurrentNode.AddEntry(index, 3, max)
+ else:
+ self.CurrentNode.SetEntry(index, 3, max)
+ elif new_valuetype == 1:
+ self.CurrentNode.SetMappingEntry(index, name = "%s%d"%(name, length), struct = 3, size = size, default = default)
+ if valuetype == 0:
+ self.CurrentNode.SetMappingEntry(index, 2, values = {"name" : "Length", "type" : 0x02, "access" : "ro", "pdo" : False})
+ self.CurrentNode.RemoveMappingEntry(index, 3)
+ self.CurrentNode.SetEntry(index, 1, type)
+ self.CurrentNode.SetEntry(index, 2, length)
+ if valuetype == 0:
+ self.CurrentNode.RemoveEntry(index, 3)
+ self.BufferCurrentNode()
+
+#-------------------------------------------------------------------------------
+# Current Buffering Management Functions
+#-------------------------------------------------------------------------------
+
+ def BufferCurrentNode(self):
+ self.UndoBuffers[self.NodeIndex].Buffering(self.CurrentNode.Copy())
+
+ def CurrentIsSaved(self):
+ return self.UndoBuffers[self.NodeIndex].IsCurrentSaved()
+
+ def OneFileHasChanged(self):
+ result = False
+ for buffer in self.UndoBuffers:
+ result |= not buffer.IsCurrentSaved()
+ return result
+
+ def GetBufferNumber(self):
+ return len(self.UndoBuffers)
+
+ def LoadCurrentPrevious(self):
+ self.CurrentNode = self.UndoBuffers[self.NodeIndex].Previous().Copy()
+
+ def LoadCurrentNext(self):
+ self.CurrentNode = self.UndoBuffers[self.NodeIndex].Next().Copy()
+
+ def AddNodeBuffer(self, currentstate = None, issaved = False):
+ self.NodeIndex = len(self.UndoBuffers)
+ self.UndoBuffers.append(UndoBuffer(currentstate, issaved))
+ self.FilePaths.append("")
+ self.FileNames.append("")
+
+ def ChangeCurrentNode(self, index):
+ if index < len(self.UndoBuffers):
+ self.NodeIndex = index
+ self.CurrentNode = self.UndoBuffers[self.NodeIndex].Current().Copy()
+ self.GenerateTypeList()
+ self.GenerateMapList()
+
+ def RemoveNodeBuffer(self, index):
+ self.UndoBuffers.pop(index)
+ self.FilePaths.pop(index)
+ self.FileNames.pop(index)
+ self.NodeIndex = min(self.NodeIndex, len(self.UndoBuffers) - 1)
+ if len(self.UndoBuffers) > 0:
+ self.CurrentNode = self.UndoBuffers[self.NodeIndex].Current().Copy()
+ self.GenerateTypeList()
+ self.GenerateMapList()
+ else:
+ self.CurrentNode = None
+
+ def GetCurrentNodeIndex(self):
+ return self.NodeIndex
+
+ def GetCurrentFilename(self):
+ return self.GetFilename(self.NodeIndex)
+
+ def GetAllFilenames(self):
+ filenames = []
+ for i in xrange(len(self.UndoBuffers)):
+ filenames.append(self.GetFilename(i))
+ return filenames
+
+ def GetFilename(self, index):
+ if self.UndoBuffers[index].IsCurrentSaved():
+ return self.FileNames[index]
+ else:
+ return "~%s~"%self.FileNames[index]
+
+ def SetCurrentFilePath(self, filepath):
+ self.FilePaths[self.NodeIndex] = filepath
+ if filepath == "":
+ self.LastNewIndex += 1
+ self.FileNames[self.NodeIndex] = "Unnamed%d"%self.LastNewIndex
+ else:
+ self.FileNames[self.NodeIndex] = os.path.splitext(os.path.basename(filepath))[0]
+
+ def GetCurrentFilePath(self):
+ if len(self.FilePaths) > 0:
+ return self.FilePaths[self.NodeIndex]
+ else:
+ return ""
+
+ def GetCurrentBufferState(self):
+ first = self.UndoBuffers[self.NodeIndex].IsFirst()
+ last = self.UndoBuffers[self.NodeIndex].IsLast()
+ return not first, not last
+
+#-------------------------------------------------------------------------------
+# Profiles Management Functions
+#-------------------------------------------------------------------------------
+
+ def GetCurrentCommunicationLists(self):
+ list = []
+ for index in MappingDictionary.iterkeys():
+ if 0x1000 <= index < 0x1200:
+ list.append(index)
+ return self.GetProfileLists(MappingDictionary, list)
+
+ def GetCurrentDS302Lists(self):
+ return self.GetSpecificProfileLists(self.CurrentNode.GetDS302Profile())
+
+ def GetCurrentProfileLists(self):
+ return self.GetSpecificProfileLists(self.CurrentNode.GetProfile())
+
+ def GetSpecificProfileLists(self, mappingdictionary):
+ validlist = []
+ exclusionlist = []
+ for name, list in self.CurrentNode.GetSpecificMenu():
+ exclusionlist.extend(list)
+ for index in mappingdictionary.iterkeys():
+ if index not in exclusionlist:
+ validlist.append(index)
+ return self.GetProfileLists(mappingdictionary, validlist)
+
+ def GetProfileLists(self, mappingdictionary, list):
+ dictionary = {}
+ current = []
+ for index in list:
+ dictionary[index] = (mappingdictionary[index]["name"], mappingdictionary[index]["need"])
+ if self.CurrentNode.IsEntry(index):
+ current.append(index)
+ return dictionary, current
+
+ def CurrentDS302Defined(self):
+ if self.CurrentNode:
+ return len(self.CurrentNode.GetDS302Profile()) > 0
+ return False
+
+#-------------------------------------------------------------------------------
+# Node State and Values Functions
+#-------------------------------------------------------------------------------
+
+ def GetCurrentNodeInfos(self):
+ name = self.CurrentNode.GetNodeName()
+ id = self.CurrentNode.GetNodeID()
+ type = self.CurrentNode.GetNodeType()
+ return name, id, type
+
+ def SetCurrentNodeInfos(self, name, id, type):
+ self.CurrentNode.SetNodeName(name)
+ self.CurrentNode.SetNodeID(id)
+ self.CurrentNode.SetNodeType(type)
+ self.BufferCurrentNode()
+
+ def GetCurrentProfileName(self):
+ if self.CurrentNode:
+ return self.CurrentNode.GetProfileName()
+ return ""
+
+ def IsCurrentEntry(self, index):
+ if self.CurrentNode:
+ return self.CurrentNode.IsEntry(index)
+ return False
+
+ def GetCurrentEntry(self, index, subIndex = None):
+ if self.CurrentNode:
+ return self.CurrentNode.GetEntry(index, subIndex)
+ return None
+
+ def GetCurrentParamsEntry(self, index, subIndex = None):
+ if self.CurrentNode:
+ return self.CurrentNode.GetParamsEntry(index, subIndex)
+ return None
+
+ def GetCurrentValidIndexes(self, min, max):
+ validindexes = []
+ for index in self.CurrentNode.GetIndexes():
+ if min <= index <= max:
+ validindexes.append((self.GetEntryName(index), index))
+ return validindexes
+
+ def GetCurrentValidChoices(self, min, max):
+ validchoices = []
+ exclusionlist = []
+ for menu, indexes in self.CurrentNode.GetSpecificMenu():
+ exclusionlist.extend(indexes)
+ good = True
+ for index in indexes:
+ good &= min <= index <= max
+ if good:
+ validchoices.append((menu, None))
+ list = [index for index in MappingDictionary.keys() if index >= 0x1000]
+ profiles = self.CurrentNode.GetMappings(False)
+ for profile in profiles:
+ list.extend(profile.keys())
+ list.sort()
+ for index in list:
+ if min <= index <= max and not self.CurrentNode.IsEntry(index) and index not in exclusionlist:
+ validchoices.append((self.GetEntryName(index), index))
+ return validchoices
+
+ def HasCurrentEntryCallbacks(self, index):
+ if self.CurrentNode and self.CurrentNode.IsEntry(index):
+ entry_infos = self.GetEntryInfos(index)
+ if "callback" in entry_infos:
+ return entry_infos["callback"]
+ return self.CurrentNode.HasEntryCallbacks(index)
+ return False
+
+ def GetCurrentEntryValues(self, index):
+ if self.CurrentNode and self.CurrentNode.IsEntry(index):
+ entry_infos = self.GetEntryInfos(index)
+ data = []
+ editors = []
+ values = self.CurrentNode.GetEntry(index)
+ params = self.CurrentNode.GetParamsEntry(index)
+ if type(values) == ListType:
+ for i, value in enumerate(values):
+ data.append({"value" : value})
+ data[-1].update(params[i])
+ else:
+ data.append({"value" : values})
+ data[-1].update(params)
+ for i, dic in enumerate(data):
+ infos = self.GetSubentryInfos(index, i)
+ dic["subindex"] = "0x%02X"%i
+ dic["name"] = infos["name"]
+ dic["type"] = self.GetTypeName(infos["type"])
+ dic["access"] = AccessType[infos["access"]]
+ dic["save"] = OptionType[dic["save"]]
+ editor = {"subindex" : None, "save" : "option", "callback" : "option", "comment" : "string"}
+ if type(values) == ListType and i == 0:
+ editor["name"] = None
+ editor["type"] = None
+ editor["access"] = None
+ editor["value"] = None
+ else:
+ if infos["user_defined"]:
+ if entry_infos["struct"] & OD_IdenticalSubindexes:
+ editor["name"] = None
+ if i > 1:
+ editor["type"] = None
+ editor["access"] = None
+ else:
+ editor["type"] = "type"
+ editor["access"] = "access"
+ else:
+ if entry_infos["struct"] & OD_MultipleSubindexes:
+ editor["name"] = "string"
+ else:
+ editor["name"] = None
+ editor["type"] = "type"
+ editor["access"] = "access"
+ else:
+ editor["name"] = None
+ editor["type"] = None
+ editor["access"] = None
+ if index < 0x260:
+ editor["value"] = None
+ if i == 1:
+ dic["value"] = self.GetTypeName(dic["value"])
+ elif 0x1600 <= index <= 0x17FF or 0x1A00 <= index <= 0x1C00:
+ editor["value"] = "map"
+ dic["value"] = self.MapTranslation["%08X"%dic["value"]]
+ else:
+ if dic["type"].startswith("VISIBLE_STRING"):
+ editor["value"] = "string"
+ elif dic["type"] == "BOOLEAN":
+ editor["value"] = "bool"
+ dic["value"] = BoolType[dic["value"]]
+ result = type_model.match(dic["type"])
+ if result:
+ values = result.groups()
+ if values[0] == "INTEGER":
+ format = "0x%0" + str(int(values[1])/4) + "X"
+ dic["value"] = format%dic["value"]
+ editor["value"] = "string"
+ elif values[0] == "UNSIGNED":
+ editor["value"] = "number"
+ elif values[0] == "REAL":
+ editor["value"] = "float"
+ elif values[0] == "VISIBLE_STRING":
+ editor["length"] = values[0]
+ result = range_model.match(dic["type"])
+ if result:
+ values = result.groups()
+ if values[0] in ("UNSIGNED", "REAL"):
+ editor["min"] = values[2]
+ editor["max"] = values[3]
+ editors.append(editor)
+ return data, editors
+ else:
+ return None
+
+#-------------------------------------------------------------------------------
+# Node Informations Functions
+#-------------------------------------------------------------------------------
+
+ def GetCustomisedTypeValues(self, index):
+ values = self.CurrentNode.GetEntry(index)
+ customisabletypes = self.GetCustomisableTypes()
+ return values, customisabletypes[values[1]][1]
+
+ def GetEntryName(self, index, node = True):
+ result = FindEntryName(index, MappingDictionary)
+ if result == None and node:
+ NodeMappings = self.CurrentNode.GetMappings()
+ i = 0
+ while not result and i < len(NodeMappings):
+ result = FindEntryName(index, NodeMappings[i])
+ i += 1
+ return result
+
+ def GetEntryInfos(self, index, node = True):
+ result = FindEntryInfos(index, MappingDictionary)
+ if result == None and node:
+ NodeMappings = self.CurrentNode.GetMappings()
+ i = 0
+ while not result and i < len(NodeMappings):
+ result = FindEntryInfos(index, NodeMappings[i])
+ i += 1
+ return result
+
+ def GetSubentryInfos(self, index, subIndex, node = True):
+ result = FindSubentryInfos(index, subIndex, MappingDictionary)
+ if result == None and node:
+ NodeMappings = self.CurrentNode.GetMappings()
+ i = 0
+ while not result and i < len(NodeMappings):
+ result = FindSubentryInfos(index, subIndex, NodeMappings[i])
+ if result:
+ result["user_defined"] = i == len(NodeMappings) - 1 and index >= 0x1000
+ i += 1
+ else :
+ result["user_defined"] = False
+ return result
+
+ def GetTypeIndex(self, typename, node = True):
+ result = FindTypeIndex(typename, MappingDictionary)
+ if result == None and node:
+ NodeMappings = self.CurrentNode.GetMappings()
+ i = 0
+ while not result and i < len(NodeMappings):
+ result = FindTypeIndex(typename, NodeMappings[i])
+ i += 1
+ return result
+
+ def GetTypeName(self, typeindex, node = True):
+ result = FindTypeName(typeindex, MappingDictionary)
+ if result == None and node:
+ NodeMappings = self.CurrentNode.GetMappings()
+ i = 0
+ while not result and i < len(NodeMappings):
+ result = FindTypeName(typeindex, NodeMappings[i])
+ i += 1
+ return result
+
+ def GetTypeDefaultValue(self, typeindex, node = True):
+ result = FindTypeDefaultValue(typeindex, MappingDictionary)
+ if result == None and node:
+ NodeMappings = self.CurrentNode.GetMappings()
+ i = 0
+ while not result and i < len(NodeMappings):
+ result = FindTypeDefaultValue(typeindex, NodeMappings[i])
+ i += 1
+ return result
+
+ def GetTypeList(self, node = True):
+ list = FindTypeList(MappingDictionary)
+ if node:
+ for NodeMapping in self.CurrentNode.GetMappings():
+ list.extend(FindTypeList(NodeMapping))
+ list.sort()
+ return list
+
+ def GetMapVariableList(self):
+ list = FindMapVariableList(MappingDictionary, self)
+ for NodeMapping in self.CurrentNode.GetMappings():
+ list.extend(FindMapVariableList(NodeMapping, self))
+ list.sort()
+ return list
+
+ def GetMandatoryIndexes(self, node = True):
+ list = FindMandatoryIndexes(MappingDictionary)
+ if node:
+ for NodeMapping in self.CurrentNode.GetMappings():
+ list.extend(FindMandatoryIndexes(NodeMapping))
+ return list
+
+ def GetCustomisableTypes(self):
+ dic = {}
+ for index, valuetype in CustomisableTypes:
+ name = self.GetTypeName(index)
+ dic[index] = [name, valuetype]
+ return dic
+
+ def GetCurrentSpecificMenu(self):
+ if self.CurrentNode:
+ return self.CurrentNode.GetSpecificMenu()
+ return []
+
+
\ No newline at end of file