def read_settings():
	try:
		f = open(fieldsConfigFile)
		
	except IOError:
		DT.error("can\'t find file or read data")
	configfile = f.readlines()
	if "KiCAD PLE Config file v1.1" in configfile[0]:
		
		for line in range(1, len(configfile)-1):
			initPos =1
			newField = kicadple.KicadField()
			# TODO 2: this will fail for lines with \r\n (windows style)
			if configfile[line][0] == "<" and configfile[line][-2] == ">":
				endPos = configfile[line].find("|");
				
				newField.name = configfile[line][initPos:endPos]
				newField.appendAlias(newField.name)
				initPos = endPos
				endPos = configfile[line].find("|",initPos+1);
				while not endPos == -1:
				
					newField.appendAlias(configfile[line][initPos+1:endPos])
					initPos = endPos
					endPos = configfile[line].find("|",initPos+1);
					
				newField.appendAlias(configfile[line][initPos+1:-2])
				
				global fieldList
				fieldList.append(newField)
		
	else:
		DT.error("incorrect config file")
Beispiel #2
0
    def parseSubCircuits(self):
        content = self.contents
        ListOfSubSchematics = []
        for count in range(len(content)):
            if "$Sheet" in content[count]:
                count += 1

                while not "$EndSheet" in content[count]:
                    # Example:
                    # F1 "ADC-16-Bit.sch" 60
                    if content[count][0:3] == "F1 ":
                        searchResult = re.search('F1 +"(.*)" +.*',
                                                 content[count])
                        if searchResult:
                            ListOfSubSchematics.append(searchResult.group(1))
                            break
                        else:
                            DT.error(
                                "cannot find schematic name in F1-record within $Sheet-block "
                                + "in file " + self.schematicName +
                                " in line number " + count)
                    count += 1
                #endwhile
            #endif $Sheet
        #endfor all lines

        self.namesOfSubcircuits = ListOfSubSchematics
Beispiel #3
0
    def setContent(self, content):
        searchResult = re.search(
            'F +(\d+) +"([^"]*)" +([HV] [0-9 A-Z]*[BN])(.*)?', content)
        # group 1: field number
        # group 2: field value (without double quotes)
        # group 3: field properties (without leading or trailing spaces)
        # group 4: optional field name (with leading/trailing spaces and double quotes)

        if searchResult:
            self.number = int(searchResult.group(1))
            self.value = searchResult.group(2)
            self._fieldProperties = searchResult.group(3)
            optFieldName = searchResult.group(
                4)  # this is optional for "F 0" to "F 3"

            if len(optFieldName) > 0:
                searchResult = re.search(' *"([^"]*).*', optFieldName)

                if searchResult:
                    self.name = searchResult.group(1)
                else:
                    self.name = ""

            searchResult = re.search(
                '([HV]) +([\d]+) +([\d]+) +([\d]+) +([\d]+) ([LRCBT]) ([LRCBT][IN][BN])',
                self._fieldProperties)
            if searchResult:
                self.orientation = searchResult.group(1)
                self.xPos = int(searchResult.group(2))
                self.yPos = int(searchResult.group(3))
                self.textSize = int(searchResult.group(4))
                self.visibility = searchResult.group(5)
                self.hAdjust = searchResult.group(6)
                self.vAdjustIB = searchResult.group(7)
            else:
                DT.error("Regex missmatch in '" + self._fieldProperties + "'")
        else:
            DT.error("Regex missmatch in ComponentField:setContent(" +
                     content + ")")
def load_schematic():
	DT.clear()
	globals.ParsedSchematicFiles = [] # clear this list.

	config = ConfigParser()
	config.read('config.ini')
    
	initialDirectory = config.get('main', 'lastDirectory', fallback="")

	if initialDirectory == "": 
		root.filename = filedialog.askopenfilename(filetypes = (("KiCAD Schematic Files",".sch"),("All Files", ".*")))
	else:
		root.filename = filedialog.askopenfilename(initialdir = initialDirectory, filetypes = (("KiCAD Schematic Files",".sch"),("All Files", ".*")))
	filename = root.filename
	root.lastSchematicFileName = filename


	config.read('config.ini')
	if config.has_section('main') == FALSE:
		config.add_section('main')
	config.set('main', 'lastDirectory', os.path.dirname(filename))
	with open('config.ini', 'w') as f:
		config.write(f)
		f.close()

	
	if filename[-4:] == ".sch" or filename[-4:] == ".SCH":
		try:
			f = open(filename)
		except IOError:
			DT.error("can\'t find file or read data")
		else:
			mainSchematicFile.setPath(filename)
			dataTestDump = f.readlines()[0]
			f.close()

		if dataTestDump[:-1] == "EESchema Schematic File Version 2" or dataTestDump[:-1] == "EESchema Schematic File Version 4": # support for KiCad4 and KiCad5
			# TODO 2: move the laoding of a schematic file into the Schematic class!
			# --> make use of recursive loading of schematics

			#verify it conforms to KiCAD specs
			if mainSchematicFile.components:
				mainSchematicFile.deleteContents()
			try:
				f = open(filename)
			except IOError:
				DT.error("can\'t find file or read data")
			else:
				mainSchematicFile.SetContents(f.readlines())
				mainSchematicFile.fieldList = fieldList;

				mainSchematicFile.schematicName = os.path.basename(filename)

				f.close()
				if mainSchematicFile.ParseComponents():
					if(len(mainSchematicFile.getSubCircuits()) != len(mainSchematicFile.getSubCircuitName())):
						messagebox.showerror("FileParseError", "Hierarchical schematics could not be found")
					else:
						messagebox.showerror("FileParseError", "This is not a valid KiCAD schematic document.")

		else:
			messagebox.showerror("FileParseError", "This is not a valid KiCAD schematic document.")

	else:
		if filename:
			messagebox.showerror("FileParseError", "This is not a valid KiCAD schematic document (*.sch or *.SCH)")


	for i in range (len(mainSchematicFile.components)):
		if "?" in mainSchematicFile.components[i].getReference():
			if messagebox.askyesno("Annotation Incomplete",
                    "The program is unable to process unanotated components. Do you want to clear imported data?"):
				mainSchematicFile.deleteContents()
			break
	root.initialDirectory = set_initial_directory(filename)

	if mainSchematicFile.schematicName:
		unlistedCount = 0
		for c in mainSchematicFile.components:
			if c.unlisted:
				unlistedCount += 1


		statusLabel['text'] = "Loaded schematic: " + mainSchematicFile.schematicName + "\n" +\
							  str(len(mainSchematicFile.components) - unlistedCount ) +\
							  " + " + str(unlistedCount) + " hidden components were found"
	else:
		statusLabel['text'] = "Start by loading a KiCad schematic file..."

	print("Summary of loading schematic: ")
	DT.summary()
Beispiel #5
0
    def extractProperties(self):

        # temporary dictionay, if we have all fields found
        fieldFound = {}
        for anyField in self.fieldList:
            fieldFound[anyField] = False

        fieldTemplate = ""  # used for new extra fields
        maxFieldNr = 3  # used for new extra fields; 0 to 3 are default fields
        lastExistingFieldLine = 0  # used for adding new extra fields; relative to $COMP (which is zero)

        for line_nr in range(len(self.contents)):
            line = self.contents[line_nr]

            # Example for a resistor with component=R and ref=R609
            # L R R609
            # the reference here is a common reference, if it is used in multiple instances of a subsheet
            if line[0] == "L":
                searchResult = re.search('L +(.*) +(.*)', line)

                if searchResult:
                    componentName = searchResult.group(1)
                    componentRef = searchResult.group(2)

                    self.reference = componentRef
                    self.name = componentName

                    DT.debug("Found Component: " + componentName + " " +
                             componentRef)

                    # Special case for power-components: don't parse them
                    if componentRef[0] == "#":
                        self.unlisted = True
                        return  # no further parsing for unlisted components

                    continue

                else:
                    DT.error("Regex Missmatch for L-record in line: " + line +
                             " in file " + self.schematicName)
                # endelse
            # endif L

            # Unit: Example
            # U 1 1 5873950B
            if line[0:2] == "U ":
                searchResult = re.search('U +(\d*) +(\d+) +([0-9A-Fa-f]+) *',
                                         line)

                if searchResult:
                    componentUnit = searchResult.group(1)
                    componentMm = searchResult.group(
                        2
                    )  # could not find a proper meaning of this value other than 'mm'
                    componentTimestamp = searchResult.group(3)  # unused here
                    self.unit = componentUnit
                    continue
                else:
                    DT.error("Regex Missmatch for 'U '-record in line: " +
                             line + " in file " + self.schematicName)
                # end else
            # endif U

            # Example:
            # AR Path="/56647084/5664BC85" Ref="U501"  Part="2"
            # the number for Part= varies e.g. from 1 to 4 for a component with 4 Units (e.g. LM324)
            # NOTE; it is not clear, for what reason we get this record only for some components...
            # we print just a message
            # for now, we don't use the data any further
            if "AR Path=" in line:
                # extract the path, Ref and Part into regex groups:
                searchResult = re.search(
                    'AR +Path="(.*)" +Ref="(.*)" +Part="(.*)".*', line)

                if searchResult:
                    componentPath = searchResult.group(1)
                    componentRef = searchResult.group(2)
                    componentUnit = searchResult.group(3)

                    # Print some messages
                    DT.debug('AR Record: ' + componentPath + ' ' +
                             componentRef + ' ' + componentUnit)

            # Example
            # F 0 "R51" H 5820 2046 50  0000 L CNN
            if line[0:4] == "F 0 ":
                if line_nr > lastExistingFieldLine:
                    lastExistingFieldLine = line_nr

                searchResult = re.search('F 0 +"(.*)" +.*', line)

                if searchResult:
                    componentRef = searchResult.group(1)

                    # TODO 1: handle proper reference name for multiple instances
                    # we get the unique references only from the AR-records!!!

                    #self.referenceUnique = componentRef

                    if not (componentRef == self.reference):
                        DT.info("L record value doesn't match 'F 0 ' record: "\
                           + self.reference + " vs. " + componentRef + " in '" +\
                          line + "' in file " + self.schematicName + ". Using 'F 0' records value: " + componentRef)
                        self.reference = componentRef
                    continue
                else:
                    DT.error("Regex Missmatch for 'F 0 '-record in line: " +\
                       line + " in file " + self.schematicName)
                # endelse
            # endif F 0

            # Value, Example:
            # F 1 "LTC2052IS#PBF" H 9750 5550 50  0000 C CNN
            if "F 1 " in line:  # find f1 indicating value field in EEschema file format
                if line_nr > lastExistingFieldLine:
                    lastExistingFieldLine = line_nr

                searchResult = re.search('F 1 +"(.*)".*', line)

                if searchResult:
                    componentValue = searchResult.group(1)
                    self.value = componentValue
                    continue
                else:
                    DT.error(
                        "Regex Mismatch, cannot find value in 'F 1 '-record in '"
                        + line + "' in file " + self.schematicName)
                # end if
            # endif F 1

            # Footprint, Example:
            # F 2 "standardSMD:R0603" V 5680 2000 50  0001 C CNN
            if "F 2 " in line:  # find f2 indicating Footprint field in EEschema file format
                if line_nr > lastExistingFieldLine:
                    lastExistingFieldLine = line_nr

                searchResult = re.search('F 2 +"(.*)".*', line)

                if searchResult:
                    componentFootprint = searchResult.group(1)
                    self.footprint = componentFootprint
                    continue
                else:
                    DT.error(
                        "Regex Mismatch, cannot find value in 'F 2 '-record (footprint) in '"
                        + line + "' in file " + self.schematicName)
                # end if
                # endif F 2

            #
            # Datasheet; Example:
            # F 3 "" H 5750 2000 50  0000 C CNN
            if "F 3 " in line:  # find f3 indicating Datasheet field in EEschema file format
                if line_nr > lastExistingFieldLine:
                    lastExistingFieldLine = line_nr

                fieldTemplate = line  # use the Datasheet field as a template for new extra fields

                searchResult = re.search('F 3 +"(.*)".*', line)

                if searchResult:
                    componentDatasheet = searchResult.group(1)
                    self.datasheet = componentDatasheet
                    continue
                else:
                    DT.error(
                        "Regex Mismatch, cannot find value in 'F 3 '-record (datasheet) in '"
                        + line + "' in file " + self.schematicName)
                # end if
                # endif F 3
            else:
                # Custom Fields, Example:
                # F 4 "C3216-100n-50V" H 8450 6050 60  0001 C CNN "InternalName"

                searchResult = re.search('F +([0-9]+) +"(.*)" +.*"(.*)".*',
                                         line)
                if searchResult:
                    if line_nr > lastExistingFieldLine:
                        lastExistingFieldLine = line_nr

                    fieldNr = int(searchResult.group(1))
                    if fieldNr > maxFieldNr:
                        maxFieldNr = fieldNr

                    fieldValue = searchResult.group(2)
                    fieldName = searchResult.group(3)
                    print(fieldValue)
                    print(fieldName)
                    tempFound = False
                    for anyField in self.fieldList:
                        for Alias in anyField.Aliases:
                            if Alias == fieldName:
                                if fieldFound[anyField] is True:
                                    DT.warning(
                                        "duplicate definition of Field " +
                                        fieldName + " with Alias " + Alias +
                                        " for Component " +
                                        self.getReference() + " in file " +
                                        self.schematicName)
                                fieldFound[anyField] = True
                                tempFound = True
                                cf = ComponentField()
                                cf.setContent(line)
                                cf.relativeLine = line_nr
                                self.propertyList.append(cf)
                                print(fieldName + "added to propertylist ")

                                break
                        if tempFound == True:
                            break
                    if tempFound == True:
                        continue
Beispiel #6
0
    def ModifyNewSCHFile(self, oldSCHFile, csvFile, savepath):
        # TODO 1: don't call this multiple times, if it is referred multiple times in parent sheets!
        # --> more efficient, avoid possible errors

        # TODO 2: improve this messages: SCH and CSV parts should match
        DT.info("Number of Parts in CSV: " + str(len(csvFile.components)))
        DT.info("Number of Parts in this SCH: " + str(len(self.components)))

        if len(csvFile.components) and len(self.components):

            for i in range(len(csvFile.components)):  #Loop over csv_components
                for p in range(len(
                        self.components)):  #loop over .sch components
                    if csvFile.components[i].reference == self.components[p].getReference() and \
                      self.schematicName ==  csvFile.components[i].getSchematic() and \
                      csvFile.components[i].unit == self.components[p].unit: #if annotation and schematic name match

                        comp = self.components[p]

                        # assign KiCad's default fields:
                        comp.name = csvFile.components[i].name
                        comp.value = csvFile.components[i].value
                        comp.footprint = csvFile.components[i].footprint
                        comp.datasheet = csvFile.components[i].datasheet

                        lineTemplate = ""

                        for ii in range(comp.startPosition, comp.endPosition):
                            line = self.contents[ii]
                            helper = ComponentField(
                            )  # helper for creating 'F x ' records

                            if line[0:2] == 'L ':
                                self.contents[
                                    ii] = 'L ' + comp.name + ' ' + comp.reference + '\n'
                            elif line[0:4] == 'F 1 ':  # component value
                                helper.setContent(line)
                                helper.value = comp.value
                                self.contents[ii] = helper.getContent()

                                lineTemplate = line  # save a template line for newly to be created fields
                            elif line[0:4] == 'F 2 ':  # component footprint
                                helper.setContent(line)
                                helper.value = comp.footprint
                                self.contents[ii] = helper.getContent()
                            elif line[0:4] == 'F 3 ':  # component datasheet
                                helper.setContent(line)
                                helper.value = comp.datasheet
                                self.contents[ii] = helper.getContent()

                        comp.updateAllMatchingFieldValues(
                            csvFile.components[i].propertyList)

                        for property in range(len(comp.propertyList)):
                            if comp.propertyList[property].exists:
                                self.contents[comp.startPosition+comp.propertyList[property].relativeLine] = \
                                 comp.propertyList[property].getContent()
                            else:
                                # otherwise we have to append it
                                self.contents[comp.startPosition+comp.propertyList[property].relativeLine] += \
                                 comp.propertyList[property].getContent()
                        # end for(all properties)
                    # end if components match
                # end for all schematic components
            #end for all csv components

            try:
                f = open(savepath, 'w')
                f.writelines(self.contents)
            except Exception as e:
                print('Error: ' + e)
                return str(e)

            for i in range(len(self.subcircuits)):
                newSavePath = os.path.join(os.path.dirname(savepath),
                                           self.namesOfSubcircuits[i])
                DT.info(newSavePath)
                self.subcircuits[i].ModifyNewSCHFile(0, csvFile, newSavePath)
                #mainFile.ModifyNewSCHFile(0, openCSVFile,savePath):
        else:
            DT.error("No components loaded")