Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add footprint Parameter to Kicad Footprint mapping #44

Merged
merged 17 commits into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 39 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,84 @@

A KiCad Conform API endpoint plugin, designed for integration with [InvenTree](https://inventree.org), empowers users to seamlessly incorporate InvenTree parts into KiCad's parts library tool. Please note that this plugin exclusively offers metadata and necessitates the presence of corresponding symbol and footprint libraries within the KiCad EDA environment.

As of the current stage of development, KiCad exclusively offers read-only access to parts through the HTTP lib interface.
As of the current stage of development, KiCad exclusively offers read-only access to parts through the HTTP lib interface.

However, this plugin provides a metadata import tool to import changes made within KiCad. This enables users to add footprints, symbols and datasheets to individual parts during the schematic design process if not already available and re-import that information into InvenTree to have it available for the next time.

## Installing the Plugin

There are several methods available for installing this plugin. To gain a comprehensive understanding of the installation process, please refer to the [InvenTree - Installing a Plugin Guide](https://docs.inventree.org/en/latest/extend/plugins/install/#installation-methods). Depending on your preferred approach, the following instructions will provide you with the necessary information.

Prior to plugin installation, ensure that you've activated both **URL Integration** and **App Integration**. You can accomplish this by going to Settings → Plugin Settings → Plugins. Additionally, if you're operating within a Docker environment, be sure to enable **Check plugins on startup** as well.

![image](https://raw.githubusercontent.com/afkiwers/inventree_kicad/main/images/plugin_general_settings.png)
![image](/images/plugin_general_settings.png)

### Through GitHub

Navigate to the **Plugin Settings** and click on the Install Plugin button. This will trigger a new window to appear, prompting you to enter the following information:

- Package Name: inventree-kicad-plugin
- Source URL: git+https://github.com/afkiwers/inventree-kicad-plugin
- Source URL: git+<https://github.com/afkiwers/inventree-kicad-plugin>

![image](https://raw.githubusercontent.com/afkiwers/inventree_kicad/main/images/install_plugin_via_github_url.png)
![image](/images/install_plugin_via_github_url.png)

### Through PiP

The plugin can be found here: [inventree-kicad-plugin](https://pypi.org/project/inventree-kicad-plugin/).

- Package Name: inventree-kicad-plugin

![image](images/pip_install.png)

![image](/images/pip_install.png)

**IMPORTANT**: Remember to restart your server and run the migrate command to implement the model changes required for this plugin. Failure to do so may result in the plugin encountering issues and not functioning correctly.

## Configure Plugin Settings

After installing the plugin, head over to the Plugin Settings and activate it. Look for **KiCadLibraryPlugin** in the list of available plugins. Once activated, you'll be able to open the plugin and proceed with the setup process.

![image](https://github.com/afkiwers/inventree_kicad/raw/main/images/admin_add_change_categories.png)
![image](/images/admin_add_change_categories.png)

## Adding Categories to KiCad

Navigate to the admin backend, and scroll down until you find the **INVENTREE_KICAD** section. Within this section, click on **KiCad Categories**.
If the section is not visible, ensure you've enabled the "Enable URL integration" and "Enable app integration" options in the Plugin Settings and run a database migration.

![image](https://github.com/afkiwers/inventree_kicad/raw/main/images/admin_model.png)
![image](/images/admin_model.png)

Once opened the "KiCad Categories" model, you'll have the option to add new categories which, once added, will be visible in KiCad's Symbol Chooser dialog.

![image](https://github.com/afkiwers/inventree_kicad/raw/main/images/admin_add_change_categories.png)
![image](/images/admin_add_change_categories.png)

#### Default Settings for Categories

The plugin allows you to set default values when the child part lacks specific details regarding the KiCad symbol, footprint, or reference. This feature is particularly useful when dealing with components such as resistors or capacitors, as they often share the same symbols, reducing the need for repetitive data entry.

![image](https://github.com/afkiwers/inventree_kicad/raw/main/images/admin_add_category.png)
![image](/images/admin_add_category.png)

#### Using Footprint Parameter Mappings

If you already have Footprint/Package Type parameters on your parts and
don't want to specify a separate KiCad Footprint Parameter for them, you
can use the Footprint Parameter Mapping functionality to map from it to
KiCad Footprint names. Simply add the desired mappings to the KiCad
Category:

![image](/images/admin_footprint_mappings.png)

You can also use this in combination with the per category "Footprint
Parameter Template" override to use a different Parameter to map from.

![image](/images/admin_footprint_parameter_override.png)

## Creating User Access Tokens

Head back to the admin backend and click on Tokens. Click on "ADD Token" to generate a token dedicated to a particular user. It is important to emphasize that it is highly advisable to create individual tokens for each user, rather than employing a single token for everyone.

![image](https://github.com/afkiwers/inventree_kicad/raw/main/images/admin_tokens.png)
![image](/images/admin_tokens.png)

## KiCad Configuration files
Below is an example config which should help you get started reasonably quickly. The only thing needed here is to replace **http://127.0.0.1:8000** with your server's InvenTree URL, and replace usertokendatastring with a valid token. Save it as a file with `.kicad_httplib` extension, as specified in the [preliminary KiCad docs](https://docs.kicad.org/master/en/eeschema/eeschema_advanced.html#http-libraries). To use it, add it as a symbol library inside KiCad.

Below is an example config which should help you get started reasonably quickly. The only thing needed here is to replace **<http://127.0.0.1:8000>** with your server's InvenTree URL, and replace usertokendatastring with a valid token. Save it as a file with `.kicad_httplib` extension, as specified in the [preliminary KiCad docs](https://docs.kicad.org/master/en/eeschema/eeschema_advanced.html#http-libraries). To use it, add it as a symbol library inside KiCad.

**Please Note**: The config file does not contain any part or category information. It merely tells KiCad what API to expect, what token to use and where to find it.

Expand All @@ -75,6 +98,7 @@ Below is an example config which should help you get started reasonably quickly.
}
}
```

## Add the HTTP library to KiCad

Inside KiCad's project manager, navigate to `Preferences -> Manage Symbol Libraries` and click on it. Add a GLobal Library by pressing the folder in the bottom left corner.
Expand All @@ -86,7 +110,7 @@ It's recommended to put a **#** as prefix to make sure it is at the top of the l

## Use in KiCad

Once everything has been configured properly, KiCad should be able to display all the categories and parts using the Symbol Picker.
Once everything has been configured properly, KiCad should be able to display all the categories and parts using the Symbol Picker.

Inside the schematic, one can either use the shortcut and press **A** or navigate to the ribbon at the top and press `Place -> Add Symbol`.

Expand All @@ -97,9 +121,9 @@ The Symbol Chooser should open up and display the parts sourced from InvenTree.
![image](/images/symbol_chooser.png)

## Importing Metadata from Previous Projects

Since KiCad does not offer a way to push information back to the server, InvenTree needs to have all that metadata such as footprints and symbols added manually. This can be very tedious, especially when there are thousands of parts.

This plugin's import tool uses KiCad's intermediate file which is created whenever there is a BOM export. This file contains all the project's data which is needed.

![image](/images/kicad_meta_data_import.png)

![image](/images/kicad_meta_data_import.png)
Binary file added images/admin_footprint_mappings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/admin_footprint_parameter_override.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 8 additions & 1 deletion inventree_kicad/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
from __future__ import unicode_literals

from django.contrib import admin
from .models import SelectedCategory, ProgressIndicator
from .models import SelectedCategory, FootprintParameterMapping, ProgressIndicator


class FootprintParameterMappingAdmin(admin.TabularInline):
model = FootprintParameterMapping
extra = 0


class SelectedCategoryAdmin(admin.ModelAdmin):
"""Admin class for the SelectedCategory model"""

inlines = [FootprintParameterMappingAdmin]
list_display = [f.name for f in SelectedCategory._meta.fields]
list_per_page = 25

Expand All @@ -29,5 +35,6 @@ def has_delete_permission(self, request, obj=None):
list_per_page = 25


admin.site.register(FootprintParameterMapping)
admin.site.register(SelectedCategory, SelectedCategoryAdmin)
admin.site.register(ProgressIndicator, ProgressIndicatorAdmin)
32 changes: 32 additions & 0 deletions inventree_kicad/migrations/0007_auto_20231212_1720.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Generated by Django 3.2.20 on 2023-12-12 16:20

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('inventree_kicad', '0006_progressindicator'),
]

operations = [
migrations.AddField(
model_name='selectedcategory',
name='footprint_parameter_template',
field=models.ForeignKey(blank=True, help_text='Footprint parameter template for this category, will use KICAD_FOOTPRINT_PARAMETER setting if not set', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='footprint_kicad_categories', to='part.partparametertemplate', verbose_name='Footprint Parameter Template'),
),
migrations.CreateModel(
name='FootprintParameterMapping',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('parameter_value', models.CharField(max_length=200, verbose_name='Footprint Parameter Value')),
('kicad_footprint', models.CharField(max_length=200, verbose_name='KiCad Footprint')),
('kicad_category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventree_kicad.selectedcategory')),
],
options={
'verbose_name': 'Footprint Mapping',
'unique_together': {('kicad_category', 'parameter_value')},
},
),
]
35 changes: 35 additions & 0 deletions inventree_kicad/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,46 @@ class Meta:
help_text=_('Default value parameter template for this category, if not specified for an individual part'),
)

footprint_parameter_template = models.ForeignKey(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was your intention with that extra parameter? It confused me a fair bit initially.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's just the existing KICAD_FOOTPRINT_PARAMETER setting, but on a per KiCad category level.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm uncertain about this particular case. We already have the settings parameter in place for that purpose. I can't envision a scenario where the footprint would be stored across multiple parameters instead of just one. It seems like that could become confusing quite rapidly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well pretty much exactly for the reason this whole PR exists.

In my case for example, I've got a whole bunch of components in InvenTree already. Some of the (resistors, capacitors, etc.) already have a "Package Type" parameter set, which I can use with the introduced functionality here, to map from said "Package Type" to a KiCad Footprint. But that "Package Type" parameter isn't set for all parts. So for some more specialized parts, like Potentiometers or certain ICs or whatever, I'd prefer to actually just add a "KiCad Footprint" parameter directly, which I can change from the InvenTree UI.

So what I'd do is set the global KICAD_FOOTPRINT_PARAMETER setting to the "KiCad Footprint" parameter and then override it for certain categories (resistors and capacitors for example) to the "Package Type" parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing confusing about that really, it's just a simple override.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah okay that makes sense now.

Would you be able to add a bit more information to the readme about when you would use which way. There are pretty much 3 then now.

Maybe include an example of some sort.

Cheers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

PartParameterTemplate,
on_delete=models.SET_NULL,
related_name="footprint_kicad_categories",
blank=True,
null=True,
verbose_name=_('Footprint Parameter Template'),
help_text=_('Footprint parameter template for this category. Overrides the KICAD_FOOTPRINT_PARAMETER setting for this category.'),
)

def __str__(self):
"""Default name string which is returned when object is called"""
return f'{self.category.pathstring}'


class FootprintParameterMapping(models.Model):
30350n marked this conversation as resolved.
Show resolved Hide resolved
"""Mapping entry to map from the footprint parameter value to a KiCad footprint name"""

class Meta:
app_label = "inventree_kicad"
verbose_name = "Footprint Mapping"
unique_together = ("kicad_category", "parameter_value")

kicad_category = models.ForeignKey(SelectedCategory, on_delete=models.CASCADE)

parameter_value = models.CharField(
30350n marked this conversation as resolved.
Show resolved Hide resolved
max_length=200,
verbose_name="Footprint Parameter Value",
)

kicad_footprint = models.CharField(
max_length=200,
verbose_name="KiCad Footprint",
)

def __str__(self):
"""Default name string which is returned when object is called"""
return f"{self.parameter_value} -> {self.kicad_footprint}"


class ProgressIndicator(models.Model):
"""Progress indicators which are used to display a loading bar inside a multiuser environment."""

Expand Down
19 changes: 16 additions & 3 deletions inventree_kicad/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from InvenTree.helpers_model import construct_absolute_url
from part.models import Part, PartCategory, PartParameter

from .models import SelectedCategory, FootprintParameterMapping


class KicadDetailedPartSerializer(serializers.ModelSerializer):
"""Custom model serializer for a single KiCad part instance"""
Expand Down Expand Up @@ -58,8 +60,6 @@ def get_kicad_category(self, part):
if hasattr(self, 'kicad_category'):
return self.kicad_category

from .models import SelectedCategory

# If the selcted part does not have a category, return None
if not part.category:
return None
Expand Down Expand Up @@ -156,18 +156,31 @@ def get_footprint(self, part):
"""Return the footprint associated with this part.

- First, check if the part has a footprint assigned (via parameter)
- Then, check if there is a valid footprint mapping
- Otherwise, fallback to the default footprint for the KiCad Category
"""

footprint = ""
footprint_mappings = None
template_id = None

if kicad_category := self.get_kicad_category(part):
footprint = kicad_category.default_footprint
footprint_mappings = FootprintParameterMapping.objects.filter(
kicad_category=kicad_category,
)
template_id = kicad_category.footprint_parameter_template

template_id = self.plugin.get_setting('KICAD_FOOTPRINT_PARAMETER', None)
if not template_id:
template_id = self.plugin.get_setting('KICAD_FOOTPRINT_PARAMETER', None)

footprint = self.get_parameter_value(part, template_id, backup_value=footprint)

if footprint_mappings:
footprint_mapping = footprint_mappings.filter(parameter_value=footprint).first()
if footprint_mapping:
footprint = footprint_mapping.kicad_footprint

return str(footprint)

def get_datasheet(self, part):
Expand Down
Loading