Пример #1
0
class _EthercatCTN(object):
    CTNChildrenTypes = [("EthercatSlave", _EthercatSlaveCTN, "Ethercat Slave")]
    if HAS_MCL:
        CTNChildrenTypes.append(
            ("EthercatCIA402Slave", _EthercatCIA402SlaveCTN,
             "Ethercat CIA402 Slave"))
    EditorType = MasterEditor

    def __init__(self):
        config_filepath = self.ConfigFileName()
        config_is_saved = False
        self.Config = None
        # if os.path.isfile(config_filepath):
        #     config_xmlfile = open(config_filepath, 'r')
        #     try:
        #         self.Config, error = \
        #             EtherCATConfigParser.LoadXMLString(config_xmlfile.read())
        #         if error is None:
        #             config_is_saved = True
        #     except Exception as e:
        #         error = str(e)
        #     config_xmlfile.close()

        #     if error is not None:
        #         self.GetCTRoot().logger.write_error(
        #             _("Couldn't load %s network configuration file.") % self.CTNName())

        if self.Config is None:
            self.Config = EtherCATConfigParser.CreateElement("EtherCATConfig")

        process_filepath = self.ProcessVariablesFileName()
        process_is_saved = False
        self.ProcessVariables = None
        if os.path.isfile(process_filepath):
            process_xmlfile = open(process_filepath, 'r', encoding='utf-8')
            try:
                self.ProcessVariables, error = \
                    ProcessVariablesParser.LoadXMLString(process_xmlfile.read())
                if error is None:
                    process_is_saved = True
            except Exception as e:
                error = str(e)
            process_xmlfile.close()

            if error is not None:
                self.GetCTRoot().logger.write_error(
                    _("Couldn't load %s network process variables file.") %
                    self.CTNName())

        if self.ProcessVariables is None:
            self.ProcessVariables = ProcessVariablesParser.CreateElement(
                "ProcessVariables")

        # if config_is_saved and process_is_saved:
        if process_is_saved:
            self.CreateBuffer(True)
        else:
            self.CreateBuffer(False)
            self.OnCTNSave()

        if os.path.isfile(config_filepath):
            config_xmlfile = open(config_filepath, 'r', encoding='utf-8')
            try:
                self.Config, error = \
                    EtherCATConfigParser.LoadXMLString(config_xmlfile.read())
                if error is None:
                    config_is_saved = True
            except Exception as e:
                error = e.message
            config_xmlfile.close()

            if error is not None:
                self.GetCTRoot().logger.write_error(
                    _("Couldn't load %s network configuration file.") %
                    self.CTNName())

        # ----------- call ethercat mng. function --------------
        self.CommonMethod = _CommonSlave(self)

    def GetIconName(self):
        return "Ethercat"

    def GetContextualMenuItems(self):
        return [(_("Add Ethercat Slave"), _("Add Ethercat Slave to Master"),
                 self.OnAddEthercatSlave)]

    def OnAddEthercatSlave(self, event):
        app_frame = self.GetCTRoot().AppFrame
        dialog = BrowseValuesLibraryDialog(app_frame, _("Ethercat Slave Type"),
                                           self.GetSlaveTypesLibrary())
        if dialog.ShowModal() == wx.ID_OK:
            type_infos = dialog.GetValueInfos()
            device, _module_extra_params = self.GetModuleInfos(type_infos)
            if device is not None:
                if HAS_MCL and str(_EthercatCIA402SlaveCTN.NODE_PROFILE
                                   ) in device.GetProfileNumbers():
                    ConfNodeType = "EthercatCIA402Slave"
                else:
                    ConfNodeType = "EthercatSlave"
                new_child = self.CTNAddChild("%s_0" % ConfNodeType,
                                             ConfNodeType)
                new_child.SetParamsAttribute("SlaveParams.Type", type_infos)
                self.CTNRequestSave()
                new_child._OpenView()
                app_frame._Refresh(TITLE, FILEMENU, PROJECTTREE)
        dialog.Destroy()

    def ExtractHexDecValue(self, value):
        return ExtractHexDecValue(value)

    def GetSizeOfType(self, type):
        return TYPECONVERSION.get(self.GetCTRoot().GetBaseType(type), None)

    def ConfigFileName(self):
        return os.path.join(self.CTNPath(), "config.xml")

    def ProcessVariablesFileName(self):
        return os.path.join(self.CTNPath(), "process_variables.xml")

    def FilterSlave(self,
                    slave,
                    vendor=None,
                    slave_pos=None,
                    slave_profile=None):
        if slave_pos is not None and slave.getInfo().getPhysAddr(
        ) != slave_pos:
            return False
        type_infos = slave.getType()
        if vendor is not None and ExtractHexDecValue(
                type_infos["vendor"]) != vendor:
            return False
        device, _module_extra_params = self.GetModuleInfos(type_infos)
        if slave_profile is not None and slave_profile not in device.GetProfileNumbers(
        ):
            return False
        return True

    def GetSlaveName(self, slave_pos):
        CTNChild = self.GetChildByIECLocation((slave_pos, ))
        if CTNChild is not None:
            return CTNChild.CTNName()
        return self.CTNName()

    def GetSlaves(self, vendor=None, slave_pos=None, slave_profile=None):
        slaves = []
        for slave in self.Config.getConfig().getSlave():
            if self.FilterSlave(slave, vendor, slave_pos, slave_profile):
                slaves.append(slave.getInfo().getPhysAddr())
        slaves.sort()
        return slaves

    def GetSlave(self, slave_pos):
        for slave in self.Config.getConfig().getSlave():
            slave_info = slave.getInfo()
            if slave_info.getPhysAddr() == slave_pos:
                return slave
        return None

    def GetStartupCommands(self,
                           vendor=None,
                           slave_pos=None,
                           slave_profile=None):
        commands = []
        for slave in self.Config.getConfig().getSlave():
            if self.FilterSlave(slave, vendor, slave_pos, slave_profile):
                commands.append((slave.getInfo().getPhysAddr(),
                                 slave.getStartupCommands()))
        commands.sort()
        return reduce(lambda x, y: x + y[1], commands, [])

    def AppendStartupCommand(self, command_infos):
        slave = self.GetSlave(command_infos["Position"])
        if slave is not None:
            command_idx = slave.appendStartupCommand(command_infos)
            self.BufferModel()
            return command_idx
        return None

    def SetStartupCommandInfos(self, command_infos):
        slave = self.GetSlave(command_infos["Position"])
        if slave is not None:
            slave.setStartupCommand(command_infos)
            self.BufferModel()

    def RemoveStartupCommand(self, slave_pos, command_idx, buffer=True):
        slave = self.GetSlave(slave_pos)
        if slave is not None:
            slave.removeStartupCommand(command_idx)
            if buffer:
                self.BufferModel()

    def SetProcessVariables(self, variables):
        vars = []
        for var in variables:
            variable = ProcessVariablesParser.CreateElement(
                "variable", "ProcessVariables")
            variable.setName(var["Name"])
            variable.setComment(var["Description"])
            if var["ReadFrom"] != "":
                position, index, subindex = var["ReadFrom"]
                if variable.getReadFrom() is None:
                    variable.addReadFrom()
                read_from = variable.getReadFrom()
                read_from.setPosition(position)
                read_from.setIndex(index)
                read_from.setSubIndex(subindex)
            elif variable.getReadFrom() is not None:
                variable.deleteReadFrom()
            if var["WriteTo"] != "":
                position, index, subindex = var["WriteTo"]
                if variable.getWriteTo() is None:
                    variable.addWriteTo()
                write_to = variable.getWriteTo()
                write_to.setPosition(position)
                write_to.setIndex(index)
                write_to.setSubIndex(subindex)
            elif variable.getWriteTo() is not None:
                variable.deleteWriteTo()
            vars.append(variable)
        self.ProcessVariables.setvariable(vars)
        self.BufferModel()

    def GetProcessVariables(self):
        variables = []
        idx = 0
        for variable in self.ProcessVariables.getvariable():
            var = {
                "Name": variable.getName(),
                "Number": idx,
                "Description": variable.getComment()
            }
            read_from = variable.getReadFrom()
            if read_from is not None:
                var["ReadFrom"] = (read_from.getPosition(),
                                   read_from.getIndex(),
                                   read_from.getSubIndex())
            else:
                var["ReadFrom"] = ""
            write_to = variable.getWriteTo()
            if write_to is not None:
                var["WriteTo"] = (write_to.getPosition(), write_to.getIndex(),
                                  write_to.getSubIndex())
            else:
                var["WriteTo"] = ""
            variables.append(var)
            idx += 1
        return variables

    def _ScanNetwork(self):
        app_frame = self.GetCTRoot().AppFrame

        execute = True
        if len(self.Children) > 0:
            dialog = wx.MessageDialog(
                app_frame,
                _("The current network configuration will be deleted.\nDo you want to continue?"
                  ), _("Scan Network"), wx.YES_NO | wx.ICON_QUESTION)
            execute = dialog.ShowModal() == wx.ID_YES
            dialog.Destroy()

        if execute:
            error, returnVal = self.RemoteExec(SCAN_COMMAND, returnVal=None)
            if error != 0:
                dialog = wx.MessageDialog(app_frame, returnVal, _("Error"),
                                          wx.OK | wx.ICON_ERROR)
                dialog.ShowModal()
                dialog.Destroy()
            elif returnVal is not None:
                for child in self.IECSortedChildren():
                    self._doRemoveChild(child)

                for slave in returnVal:
                    type_infos = {
                        "vendor": slave["vendor_id"],
                        "product_code": slave["product_code"],
                        "revision_number": slave["revision_number"],
                    }
                    device, _module_extra_params = self.GetModuleInfos(
                        type_infos)
                    if device is not None:
                        if HAS_MCL and _EthercatCIA402SlaveCTN.NODE_PROFILE in device.GetProfileNumbers(
                        ):
                            CTNType = "EthercatCIA402Slave"
                        else:
                            CTNType = "EthercatSlave"
                        self.CTNAddChild("slave%s" % slave["idx"], CTNType,
                                         slave["idx"])
                        self.SetSlaveAlias(slave["idx"], slave["alias"])
                        type_infos["device_type"] = device.getType(
                        ).getcontent()
                        self.SetSlaveType(slave["idx"], type_infos)

                if app_frame:
                    app_frame.RefreshProjectTree()

    def CTNAddChild(self, CTNName, CTNType, IEC_Channel=0):
        """
        Create the confnodes that may be added as child to this node self
        @param CTNType: string desining the confnode class name (get name from CTNChildrenTypes)
        @param CTNName: string for the name of the confnode instance
        """
        newConfNodeOpj = ConfigTreeNode.CTNAddChild(self, CTNName, CTNType,
                                                    IEC_Channel)

        slave = self.GetSlave(newConfNodeOpj.BaseParams.getIEC_Channel())
        if slave is None:
            slave = EtherCATConfigParser.CreateElement("Slave", "Config")
            self.Config.getConfig().appendSlave(slave)
            slave_infos = slave.getInfo()
            slave_infos.setName("undefined")
            slave_infos.setPhysAddr(newConfNodeOpj.BaseParams.getIEC_Channel())
            slave_infos.setAutoIncAddr(0)
            self.BufferModel()
            self.OnCTNSave()

        return newConfNodeOpj

    def _doRemoveChild(self, CTNInstance):
        slave_pos = CTNInstance.GetSlavePos()
        config = self.Config.getConfig()
        for idx, slave in enumerate(config.getSlave()):
            slave_infos = slave.getInfo()
            if slave_infos.getPhysAddr() == slave_pos:
                config.removeSlave(idx)
                self.BufferModel()
                self.OnCTNSave()
        ConfigTreeNode._doRemoveChild(self, CTNInstance)

    def SetSlavePosition(self, slave_pos, new_pos):
        slave = self.GetSlave(slave_pos)
        if slave is not None:
            slave_info = slave.getInfo()
            slave_info.setPhysAddr(new_pos)
            for variable in self.ProcessVariables.getvariable():
                read_from = variable.getReadFrom()
                if read_from is not None and read_from.getPosition(
                ) == slave_pos:
                    read_from.setPosition(new_pos)
                write_to = variable.getWriteTo()
                if write_to is not None and write_to.getPosition(
                ) == slave_pos:
                    write_to.setPosition(new_pos)
            self.CreateBuffer(True)
            self.CTNRequestSave()
            if self._View is not None:
                self._View.RefreshView()
                self._View.RefreshBuffer()

    def GetSlaveAlias(self, slave_pos):
        slave = self.GetSlave(slave_pos)
        if slave is not None:
            slave_info = slave.getInfo()
            return slave_info.getAutoIncAddr()
        return None

    def SetSlaveAlias(self, slave_pos, alias):
        slave = self.GetSlave(slave_pos)
        if slave is not None:
            slave_info = slave.getInfo()
            slave_info.setAutoIncAddr(alias)
            self.BufferModel()

    def GetSlaveType(self, slave_pos):
        slave = self.GetSlave(slave_pos)
        if slave is not None:
            return slave.getType()
        return None

    def SetSlaveType(self, slave_pos, type_infos):
        slave = self.GetSlave(slave_pos)
        if slave is not None:
            slave.setType(type_infos)
            self.BufferModel()

    def GetSlaveInfos(self, slave_pos):
        slave = self.GetSlave(slave_pos)
        if slave is not None:
            type_infos = slave.getType()
            device, _module_extra_params = self.GetModuleInfos(type_infos)
            if device is not None:
                infos = type_infos.copy()
                infos.update({
                    "physics": device.getPhysics(),
                    "sync_managers": device.GetSyncManagers(),
                    "entries": self.GetSlaveVariables(device)
                })
                return infos
        return None

    def GetSlaveVariables(self,
                          slave_pos=None,
                          limits=None,
                          device=None,
                          module=None):
        # add jblee
        files = os.listdir(self.CTNPath())
        moduleNames = []
        modulePos = 1
        for file in files:
            filepath = os.path.join(self.CTNPath(), file)
            if os.path.isdir(filepath):
                MDPFilePath = os.path.join(filepath, "DataForMDP.txt")
                CheckConfNodePath = os.path.join(filepath, "baseconfnode.xml")

                try:
                    moduleDataFile = open(MDPFilePath, 'r', encoding='utf-8')
                    confNodeFile = open(CheckConfNodePath,
                                        'r',
                                        encoding='utf-8')

                    lines = moduleDataFile.readlines()
                    checklines = confNodeFile.readlines()

                    moduleDataFile.close()
                    confNodeFile.close()

                    module_info = self.GetModuleEntryList()
                    # checklines(ex) : <BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="0" Name="EthercatSlave_0"/>
                    # checklines[1].split() : [<BaseParams, xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                    #                           IEC_Channel="0", Name="EthercatSlave_0"/>]
                    # checklines[1].split()[2] : IEC_Channel="0"
                    # checklines[1].split()[2].split("\"") = [IEC_Channel=, 0, ]
                    pos_check = int(checklines[1].split()[2].split("\"")[1])

                    if slave_pos != pos_check:
                        continue

                    for line in lines:
                        if line == "\n":
                            continue
                        # module_name : ST-1214, ST-2314, ...
                        # if user add module => ST-1214 3EA, ST-2314 3EA
                        # each result_module_name :
                        #    (ST-1214, Module 1), (ST-1214, Module 2), (ST-1214, Module 3)
                        #    (ST-2314, Module 4), (ST-2314, Module 5), (ST-2314, Module 6)
                        module_name = line.split()[0]
                        result_module_name = module_name + ", Module %d" % modulePos
                        moduleNames.append(result_module_name)
                        modulePos += 1
                except:
                    pass

        if device is None and slave_pos is not None:
            slave = self.GetSlave(slave_pos)
            if slave is not None:
                type_infos = slave.getType()
                device, _module_extra_params = self.GetModuleInfos(type_infos)
        if device is not None:
            # Test OD
            entries = device.GetEntriesList(limits)
            # entries = self.CTNParent.GetEntriesList()
            entries_list = list(entries.items())
            entries_list.sort()
            entries = []
            current_index = None
            current_entry = {}
            for (index, _subindex), entry in entries_list:
                entry["children"] = []
                if slave_pos is not None:
                    entry["Position"] = str(slave_pos)
                if index != current_index:
                    current_index = index
                    current_entry = entry
                    entries.append(entry)
                elif current_entry:
                    current_entry["children"].append(entry)
                else:
                    entries.append(entry)

            increment = self.CTNParent.GetModuleIncrement()[0]
            count = 1
            # print module_info
            # moduleNameAndPos : (ST-1214, Module 1), (ST-1214, Module 2), ... ,
            # moduleNameAndPos.split(",") : ["ST-1214", " Module 1"]
            # moduleNameAndPos.split(",")[0] : "ST-1214"
            for moduleNameAndPos in moduleNames:
                moduleName = moduleNameAndPos.split(",")[0]
                modulePosName = moduleNameAndPos.split(",")[1]
                idx_increment = int(increment) * count

                for MDP_entry in module_info.get(moduleName):
                    LocalMDPEntry = []
                    # print MDP_entry
                    local_idx = MDP_entry["Index"]
                    if ExtractHexDecValue(
                            local_idx) == 0:  # and local_idx[0] == "#":
                        temp_index = ExtractHexDecValue(local_idx)
                    else:
                        temp_index = ExtractHexDecValue(
                            MDP_entry["Index"]) + idx_increment
                    # temp_index = ExtractHexDecValue(MDP_entry["Index"]) + idx_increment
                    entry_index = hex(temp_index)
                    entry_subidx = MDP_entry["SubIndex"]
                    entry_name = MDP_entry["Name"] + ", " + " " + \
                                 moduleName + " - " + modulePosName
                    entry_type = MDP_entry["Type"]
                    entry_bitsize = MDP_entry["BitSize"]
                    entry_access = MDP_entry["Access"]
                    mapping_type = MDP_entry["PDOMapping"]

                    LocalMDPEntry.append({
                        "Index": entry_index,
                        "SubIndex": entry_subidx,
                        "Name": entry_name,
                        "Type": entry_type,
                        "BitSize": entry_bitsize,
                        "Access": entry_access,
                        "PDOMapping": mapping_type,
                        "children": ""
                    })
                    entries.append(LocalMDPEntry[0])
                count += 1

            # print entries
            return entries
        return []

    def GetSlaveVariableDataType(self, slave_pos, index, subindex):
        slave = self.GetSlave(slave_pos)
        if slave is not None:
            device, _module_extra_params = self.GetModuleInfos(slave.getType())
            if device is not None:
                entries = device.GetEntriesList()
                entry_infos = entries.get((index, subindex))
                if entry_infos is not None:
                    return entry_infos["Type"]
        return None

    def GetNodesVariables(self,
                          vendor=None,
                          slave_pos=None,
                          slave_profile=None,
                          limits=None):
        entries = []
        for slave_position in self.GetSlaves():
            if slave_pos is not None and slave_position != slave_pos:
                continue
            slave = self.GetSlave(slave_position)
            type_infos = slave.getType()
            if vendor is not None and ExtractHexDecValue(
                    type_infos["vendor"]) != vendor:
                continue
            device, _module_extra_params = self.GetModuleInfos(type_infos)
            if slave_profile is not None and slave_profile not in device.GetProfileNumbers(
            ):
                continue
            entries.extend(
                self.GetSlaveVariables(slave_position, limits, device))
        return entries

    def GetModuleInfos(self, type_infos):
        return self.CTNParent.GetModuleInfos(type_infos)

    # add jblee
    def GetModuleEntryList(self):
        return self.CTNParent.GetModuleEntryList()

    def GetSlaveTypesLibrary(self, profile_filter=None):
        return self.CTNParent.GetModulesLibrary(profile_filter)

    def GetLibraryVendors(self):
        return self.CTNParent.GetVendors()

    def GetDeviceLocationTree(self, slave_pos, current_location, device_name):
        slave = self.GetSlave(slave_pos)
        vars = []

        # add jblee
        files = os.listdir(self.CTNPath())
        moduleNames = []
        modulePos = 1
        for file in files:
            filepath = os.path.join(self.CTNPath(), file)
            if os.path.isdir(filepath):
                MDPFilePath = os.path.join(filepath, "DataForMDP.txt")
                CheckConfNodePath = os.path.join(filepath, "baseconfnode.xml")

                try:
                    moduleDataFile = open(MDPFilePath, 'r', encoding='utf-8')
                    confNodeFile = open(CheckConfNodePath,
                                        'r',
                                        encoding='utf-8')

                    lines = moduleDataFile.readlines()
                    checklines = confNodeFile.readlines()

                    moduleDataFile.close()
                    confNodeFile.close()

                    module_info = self.GetModuleEntryList()
                    # checklines(ex) : <BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="0" Name="EthercatSlave_0"/>
                    # checklines[1].split() : [<BaseParams, xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                    #                           IEC_Channel="0", Name="EthercatSlave_0"/>]
                    # checklines[1].split()[2] : IEC_Channel="0"
                    # checklines[1].split()[2].split("\"") = [IEC_Channel=, 0, ]
                    pos_check = int(checklines[1].split()[2].split("\"")[1])

                    if slave_pos != pos_check:
                        continue

                    for line in lines:
                        if line == "\n":
                            continue
                        # module_name : ST-1214, ST-2314, ...
                        # if user add module => ST-1214 3EA, ST-2314 3EA
                        # each result_module_name :
                        #    (ST-1214, Module 1), (ST-1214, Module 2), (ST-1214, Module 3)
                        #    (ST-2314, Module 4), (ST-2314, Module 5), (ST-2314, Module 6)
                        module_name = line.split()[0]
                        result_module_name = module_name + ", Module %d" % modulePos
                        moduleNames.append(result_module_name)
                        modulePos += 1
                except:
                    pass

        if slave is not None:
            type_infos = slave.getType()

            device, _module_extra_params = self.GetModuleInfos(type_infos)
            if device is not None:
                sync_managers = []
                for sync_manager in device.getSm():
                    sync_manager_control_byte = ExtractHexDecValue(
                        sync_manager.getControlByte())
                    sync_manager_direction = sync_manager_control_byte & 0x0c
                    if sync_manager_direction:
                        sync_managers.append(LOCATION_VAR_OUTPUT)
                    else:
                        sync_managers.append(LOCATION_VAR_INPUT)

                entries = list(device.GetEntriesList().items())
                entries.sort()
                for (index, subindex), entry in entries:
                    var_size = self.GetSizeOfType(entry["Type"])
                    if var_size is not None:
                        var_class = VARCLASSCONVERSION.get(
                            entry["PDOMapping"], None)
                        if var_class is not None:
                            if var_class == LOCATION_VAR_INPUT:
                                var_dir = "%I"
                            else:
                                var_dir = "%Q"

                            vars.append({
                                "name":
                                "0x%4.4x-0x%2.2x: %s" %
                                (index, subindex, entry["Name"]),
                                "type":
                                var_class,
                                "size":
                                var_size,
                                "IEC_type":
                                entry["Type"],
                                "var_name":
                                "%s_%4.4x_%2.2x" % ("_".join(
                                    device_name.split()), index, subindex),
                                "location":
                                "%s%s%s" % (var_dir, var_size, ".".join(
                                    map(str, current_location +
                                        (index, subindex)))),
                                "description":
                                "",
                                "children": [],
                            })

                # add jblee for MDP
                if not entries:
                    increment = self.CTNParent.GetModuleIncrement()[0]
                    count = 1
                    for moduleNameAndPos in moduleNames:
                        moduleName = moduleNameAndPos.split(",")[0]
                        idx_increment = int(increment) * count
                        for MDP_entry in module_info.get(moduleName):
                            local_idx = MDP_entry["Index"]
                            if ExtractHexDecValue(
                                    local_idx) != 0 and local_idx[0] == "#":
                                index = ExtractHexDecValue(
                                    local_idx) + idx_increment
                            else:
                                index = ExtractHexDecValue(MDP_entry["Index"])
                            subindex = int(MDP_entry["SubIndex"])
                            var_class = VARCLASSCONVERSION.get(
                                MDP_entry["PDOMapping"], None)
                            if var_class is not None:
                                if var_class == LOCATION_VAR_INPUT:
                                    var_dir = "%I"
                                else:
                                    var_dir = "%Q"
                            var_size = self.GetSizeOfType(MDP_entry["Type"])
                            result_name = MDP_entry[
                                "Name"] + ", " + moduleNameAndPos
                            vars.append({
                                "name":
                                "0x%4.4x-0x%2.2x: %s" %
                                (index, subindex, result_name),
                                "type":
                                var_class,
                                "size":
                                var_size,
                                "IEC_type":
                                MDP_entry["Type"],
                                "var_name":
                                "%s_%4.4x_%2.2x" % ("_".join(
                                    moduleName.split()), index, subindex),
                                "location":
                                "%s%s%s" % (var_dir, var_size, ".".join(
                                    map(str, current_location +
                                        (index, subindex)))),
                                "description":
                                "",
                                "children": []
                            })
                        count += 1

        return vars

    def CTNTestModified(self):
        return self.ChangesToSave or not self.ModelIsSaved()

    def OnCTNSave(self, from_project_path=None):
        config_filepath = self.ConfigFileName()
        config_xmlfile = open(config_filepath, "w", encoding='utf-8')
        config_xmlfile.write(
            etree.tostring(self.Config,
                           pretty_print=True,
                           xml_declaration=True,
                           encoding='utf-8').decode())
        config_xmlfile.close()

        process_filepath = self.ProcessVariablesFileName()

        process_xmlfile = open(process_filepath, "w", encoding='utf-8')
        process_xmlfile.write(
            etree.tostring(self.ProcessVariables,
                           pretty_print=True,
                           xml_declaration=True,
                           encoding='utf-8').decode())
        process_xmlfile.close()

        self.Buffer.CurrentSaved()
        return True

    def GetProcessVariableName(self, location, var_type):
        return "__M%s_%s" % (self.GetSizeOfType(var_type), "_".join(
            map(str, location)))

    def _Generate_C(self, buildpath, locations):
        current_location = self.GetCurrentLocation()
        # define a unique name for the generated C file
        location_str = "_".join(map(str, current_location))

        Gen_Ethercatfile_path = os.path.join(buildpath,
                                             "ethercat_%s.c" % location_str)

        self.FileGenerator = _EthercatCFileGenerator(self)

        LocationCFilesAndCFLAGS, LDFLAGS, extra_files = ConfigTreeNode._Generate_C(
            self, buildpath, locations)

        for idx, variable in enumerate(self.ProcessVariables.getvariable()):
            name = None
            var_type = None
            read_from = variable.getReadFrom()
            write_to = variable.getWriteTo()
            if read_from is not None:
                pos = read_from.getPosition()
                index = read_from.getIndex()
                subindex = read_from.getSubIndex()
                location = current_location + (idx, )
                var_type = self.GetSlaveVariableDataType(pos, index, subindex)
                name = self.FileGenerator.DeclareVariable(
                    pos, index, subindex, var_type, "I",
                    self.GetProcessVariableName(location, var_type))
            if write_to is not None:
                pos = write_to.getPosition()
                index = write_to.getIndex()
                subindex = write_to.getSubIndex()
                if name is None:
                    location = current_location + (idx, )
                    var_type = self.GetSlaveVariableDataType(
                        pos, index, subindex)
                    name = self.GetProcessVariableName(location, var_type)
                self.FileGenerator.DeclareVariable(pos, index, subindex,
                                                   var_type, "Q", name, True)

        self.FileGenerator.GenerateCFile(Gen_Ethercatfile_path, location_str,
                                         self.BaseParams.getIEC_Channel())

        LocationCFilesAndCFLAGS.insert(0, (current_location, [
            (Gen_Ethercatfile_path,
             '"-I%s"' % os.path.abspath(self.GetCTRoot().GetIECLibPath()))
        ], True))
        LDFLAGS.append("-lethercat_rtdm -lrtdm")

        return LocationCFilesAndCFLAGS, LDFLAGS, extra_files

    ConfNodeMethods = [
        {
            "bitmap": "ScanNetwork",
            "name": _("Scan Network"),
            "tooltip": _("Scan Network"),
            "method": "_ScanNetwork",
        },
    ]

    def CTNGenerate_C(self, buildpath, locations):
        current_location = self.GetCurrentLocation()

        slaves = self.GetSlaves()
        for slave_pos in slaves:
            slave = self.GetSlave(slave_pos)
            if slave is not None:
                self.FileGenerator.DeclareSlave(slave_pos, slave)

        for location in locations:
            loc = location["LOC"][len(current_location):]
            slave_pos = loc[0]
            if slave_pos in slaves and len(
                    loc) == 3 and location["DIR"] != "M":
                self.FileGenerator.DeclareVariable(slave_pos, loc[1], loc[2],
                                                   location["IEC_TYPE"],
                                                   location["DIR"],
                                                   location["NAME"])

        return [], "", False

    # -------------------------------------------------------------------------------
    #                      Current Buffering Management Functions
    # -------------------------------------------------------------------------------

    def Copy(self, model):
        """Return a copy of the config"""
        return deepcopy(model)

    def CreateBuffer(self, saved):
        self.Buffer = UndoBuffer((EtherCATConfigParser.Dumps(
            self.Config), ProcessVariablesParser.Dumps(self.ProcessVariables)),
                                 saved)

    def BufferModel(self):
        self.Buffer.Buffering(
            (EtherCATConfigParser.Dumps(self.Config),
             ProcessVariablesParser.Dumps(self.ProcessVariables)))

    def ModelIsSaved(self):
        if self.Buffer is not None:
            return self.Buffer.IsCurrentSaved()
        else:
            return True

    def LoadPrevious(self):
        config, process_variables = self.Buffer.Previous()
        self.Config = EtherCATConfigParser.Loads(config)
        self.ProcessVariables = ProcessVariablesParser.Loads(process_variables)

    def LoadNext(self):
        config, process_variables = self.Buffer.Next()
        self.Config = EtherCATConfigParser.Loads(config)
        self.ProcessVariables = ProcessVariablesParser.Loads(process_variables)

    def GetBufferState(self):
        first = self.Buffer.IsFirst()
        last = self.Buffer.IsLast()
        return not first, not last
Пример #2
0
class CodeFile(object):
    CODEFILE_NAME = "CodeFile"
    SECTIONS_NAMES = []

    def __init__(self):
        sections_str = {"codefile_name": self.CODEFILE_NAME}
        if "includes" in self.SECTIONS_NAMES:
            sections_str["includes_section"] = SECTION_TAG_ELEMENT % "includes"
        else:
            sections_str["includes_section"] = ""
        sections_str["sections"] = "\n".join(
            [SECTION_TAG_ELEMENT % name
             for name in self.SECTIONS_NAMES if name != "includes"])

        self.CodeFileParser = GenerateParserFromXSDstring(
            CODEFILE_XSD % sections_str)
        self.CodeFileVariables = etree.XPath("variables/variable")

        filepath = self.CodeFileName()
        if os.path.isfile(filepath):
            xmlfile = open(filepath, 'r', encoding='utf-8')
            codefile_xml = xmlfile.read()
            xmlfile.close()

            codefile_xml = codefile_xml.replace(
                '<%s>' % self.CODEFILE_NAME,
                '<%s xmlns:xhtml="http://www.w3.org/1999/xhtml">' % self.CODEFILE_NAME)
            for cre, repl in [
                (re.compile(r"(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
                (re.compile(r"(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
                codefile_xml = cre.sub(repl, codefile_xml)

            try:
                self.CodeFile, error = self.CodeFileParser.LoadXMLString(codefile_xml)
                if error is not None:
                    (fname, lnum, src) = ((self.CODEFILE_NAME,) + error)
                    self.GetCTRoot().logger.write_warning(XSDSchemaErrorMessage.format(a1=fname, a2=lnum, a3=src))
                self.CreateCodeFileBuffer(True)
            except Exception as exc:
                msg = _("Couldn't load confnode parameters {a1} :\n {a2}").format(a1=self.CTNName(), a2=str(exc))
                self.GetCTRoot().logger.write_error(msg)
                print(traceback.format_exc())
                raise Exception
        else:
            self.CodeFile = self.CodeFileParser.CreateRoot()
            self.CreateCodeFileBuffer(False)
            self.OnCTNSave()

    def GetBaseTypes(self):
        return self.GetCTRoot().GetBaseTypes()

    def GetDataTypes(self, basetypes=False):
        return self.GetCTRoot().GetDataTypes(basetypes=basetypes)

    def GenerateNewName(self, name, format):
        return self.GetCTRoot().GenerateNewName(
            None, name, format,
            exclude=dict([(var.getname().upper(), True)
                          for var in self.CodeFile.variables.getvariable()]))

    def SetVariables(self, variables):
        self.CodeFile.variables.setvariable([])
        for var in variables:
            variable = self.CodeFileParser.CreateElement("variable", "variables")
            variable.setname(var["Name"])
            variable.settype(var["Type"])
            variable.setinitial(var["Initial"])
            variable.setdesc(var["Description"])
            variable.setonchange(var["OnChange"])
            variable.setopts(var["Options"])
            self.CodeFile.variables.appendvariable(variable)

    def GetVariables(self):
        datas = []
        for var in self.CodeFileVariables(self.CodeFile):
            datas.append({
                "Name": var.getname(),
                "Type": var.gettype(),
                "Initial": var.getinitial(),
                "Description": var.getdesc(),
                "OnChange": var.getonchange(),
                "Options": var.getopts(),
            })
        return datas

    def SetTextParts(self, parts):
        for section in self.SECTIONS_NAMES:
            section_code = parts.get(section)
            if section_code is not None:
                getattr(self.CodeFile, section).setanyText(section_code)

    def GetTextParts(self):
        return dict([(section, getattr(self.CodeFile, section).getanyText())
                     for section in self.SECTIONS_NAMES])

    def CTNTestModified(self):
        return self.ChangesToSave or not self.CodeFileIsSaved()

    def OnCTNSave(self, from_project_path=None):
        filepath = self.CodeFileName()

        xmlfile = open(filepath, "w", encoding='utf-8')
        xmlfile.write(etree.tostring(
            self.CodeFile,
            pretty_print=True,
            xml_declaration=True,
            encoding='utf-8').decode())
        xmlfile.close()

        self.MarkCodeFileAsSaved()
        return True

    def CTNGlobalInstances(self):
        variables = self.CodeFileVariables(self.CodeFile)
        ret = [(variable.getname(),
                variable.gettype(),
                variable.getinitial())
               for variable in variables]
        ret.extend([("On" + variable.getname() + "Change", "python_poll", "")
                    for variable in variables
                    if variable.getonchange()])
        return ret

    def CTNSearch(self, criteria):
        variables = self.GetVariables()
        results = []
        tagname = self.CTNFullName()
        for index, var in enumerate(variables):
            varname = var["Name"]
            results.extend([((tagname, "var_inout", index, "name"),) + result
                            for result in TestTextElement(varname, criteria)])
        results.extend([((tagname, "body"),) + result
                        for result in TestTextElement(
                GetSectionsText(self, lambda x: ""), criteria)])
        return results
    # -------------------------------------------------------------------------------
    #                      Current Buffering Management Functions
    # -------------------------------------------------------------------------------

    def Copy(self, model):
        """
        Return a copy of the codefile model
        """
        return deepcopy(model)

    def CreateCodeFileBuffer(self, saved):
        self.Buffering = False
        self.CodeFileBuffer = UndoBuffer(self.CodeFileParser.Dumps(self.CodeFile), saved)

    def BufferCodeFile(self):
        self.CodeFileBuffer.Buffering(self.CodeFileParser.Dumps(self.CodeFile))

    def StartBuffering(self):
        self.Buffering = True

    def EndBuffering(self):
        if self.Buffering:
            self.CodeFileBuffer.Buffering(self.CodeFileParser.Dumps(self.CodeFile))
            self.Buffering = False

    def MarkCodeFileAsSaved(self):
        self.EndBuffering()
        self.CodeFileBuffer.CurrentSaved()

    def CodeFileIsSaved(self):
        return self.CodeFileBuffer.IsCurrentSaved() and not self.Buffering

    def LoadPrevious(self):
        self.EndBuffering()
        self.CodeFile = self.CodeFileParser.Loads(self.CodeFileBuffer.Previous())

    def LoadNext(self):
        self.CodeFile = self.CodeFileParser.Loads(self.CodeFileBuffer.Next())

    def GetBufferState(self):
        first = self.CodeFileBuffer.IsFirst() and not self.Buffering
        last = self.CodeFileBuffer.IsLast()
        return not first, not last
Пример #3
0
 def CreateBuffer(self, saved):
     self.Buffer = UndoBuffer((EtherCATConfigParser.Dumps(
         self.Config), ProcessVariablesParser.Dumps(self.ProcessVariables)),
                              saved)
Пример #4
0
 def CreateCodeFileBuffer(self, saved):
     self.Buffering = False
     self.CodeFileBuffer = UndoBuffer(self.CodeFileParser.Dumps(self.CodeFile), saved)