diff --git a/README.md b/README.md
index 2b2f6dc..284cd5f 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,8 @@ This plugin depends on [qrcode](https://github.com/lincolnloop/python-qrcode) an
| 0.0.11 | >= 3.7.0 | 3.7.x |
| 0.0.13 | >= 4.0.2 | v4.0.2 |
+Netbox version 2 is no longer supported.
+
## Installation
If Netbox was installed according to the standard installation instructions. It may be necessary to activate the virtual environment.
@@ -36,74 +38,53 @@ Restart NetBox and add `netbox-qrcode` to your local_requirements.txt
## Configuration
-The following options are available:
+### Set the label printer correctly
-* `with_text`: Boolean (default True). Text label will be added to QR code image if enabled.
-* `text_template`: [Jinja2](https://jinja.palletsprojects.com/) template with {{ obj }} as context for device, rack, etc., using it ignores `text_fields` and `custom_text`.
+If the print does not look like the preview in the Netbox, first try to get a perfect print using Word. As many printer settings also have an influence on the print result. Borderless printing is possible if the printer (e.g. thermal transfer printer) supports this.
- Example to output name and site in two lines with caption (See also screenshots below):
- ```
- 'text_template': 'Name: {{ obj.name }}\nSite: {{ obj.site }}',
- ```
-* `text_fields`: List of String (default ['name']). Text fields of an object that will be added as text label to QR image. It's possible to use custom field values.
-* `font`: String (default TahomaBold) Font name for text label ( Some font include in package, see fonts dir).
-* `text_location`: Where to render the text, relative to the QR code. Valid values are `"right"` (default), `"left"`", `"up"`, and `"down"`.
-* `custom_text`: String or None (default None) additional text label to QR code image (will be added after text_fields).
-* `qr_version`: Integer (default 1) parameter is an integer from 1 to 40 that controls the size of
-the QR Code (the smallest, version 1, is a 21x21 matrix).
-* `qr_error_correction`: Integer (default 0), controls the error correction used for the
-QR Code. The following values are available:
+![ShowImage](/docs/img/Configuration_Printer_WordPreview.png)
- 1 - About 7% or less errors can be corrected.
- 0 - About 15% or less errors can be corrected.
- 2 - About 30% or less errors can be corrected.
- 3 - About 25% or less errors can be corrected.
-* `qr_box_size`: Integer (default 6), controls how many pixels each "box" of the QR code
-is.
-* `qr_border`: Integer (default 4), controls how many boxes thick the border should be
-(the default is 4, which is the minimum according to the specs).
+Here is an example of what needs to be considered to print borderless from a Word document. [Go to: Eexample Zebra ZM400 300dpi label printer and a label 56x32mm. >>](/docs/img/Configuration_Printer_ZM400.png)
-### Per object options
-Per object options override default options. Per object options dictionary can contains any of default options inside.
+### Browser Print Settings correctly
-* `device`: Dict or None (default {'text_fields': ['name', 'serial']}), set None to disble QR code
-* `rack`: Dict or None (default {'text_fields': ['name']}) , set None to disble QR code
-* `cable`: Dict or None ( defaul {'text_fields': ['_termination_a_device', 'termination_a', '_termination_b_device', 'termination_b',]}), set None to disble QR code
+When you press the “Print” button, there are some print properties that are added by the browser. However, these interfere with the print result. They should therefore be deactivated.
-Configuration example:
-```
-PLUGINS_CONFIG = {
- 'netbox_qrcode': {
- 'with_text': True,
- 'text_fields': ['name', 'serial'],
- 'font': 'ArialMT',
- 'font_size': 12, # If the value is 0 or the line does not exist, then the text is automatically adjusted
- 'custom_text': 'Property of SomeCompany\ntel.8.800333554-CALL',
- 'text_location': 'up',
- 'qr_version': 1,
- 'qr_error_correction': 0,
- 'qr_box_size': 4,
- 'qr_border': 4,
- # per object options
- 'cable': None, # disable QR code for Cable object
- 'rack': {
- 'text_fields': [
- 'site',
- 'name',
- 'facility_id',
- 'tenant',
- 'cf.cf_name'
- ]
- },
- 'device': {
- 'qr_box_size': 6,
- 'custom_text': None,
- }
- }
-}
-```
+#### Firefox:
+
+| Parameter | Value |
+| --------------------------------------------- | --------------------------- |
+| Orientation | Portrait |
+| Paper size | User defined |
+| Margins | none |
+| Scale | Fit to page width or 100% |
+| Options --> Print headers and footers | disable |
+| Options --> Print backgrounds | disable |
+
+#### Chrome:
+The worst part was finding the right parameters for Chrome. Because it always turned it differently when printing than the print preview shows.
+| Parameter | Value |
+| --------------------------------------------- | --------------------------- |
+| Layout | Portrait |
+| Paper size | empty !!! |
+| Pages per sheet | 1 |
+| Margins | none |
+| Scale | Default or 100% |
+| Options --> PBackground grafics | disable |
+
+![Image](/docs/img/Configuration_Browser_Print_Settings.png)
+
+
+### Design your own label
+
+You can customise the label as you wish, even 2 different labels for the ‘Device’ view, for example, are possible.
+
+- [Go to Configuration >>](docs/README_Subpages/README_Configuration.md)
+- [Go to Example label configurations >>](docs/README_Subpages/README_Configuration_ExampleLabelConf.md)
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_10.png)
## Contributing
Developing tools for this project based on [ntc-netbox-plugin-onboarding](https://github.com/networktocode/ntc-netbox-plugin-onboarding) repo.
@@ -119,7 +100,4 @@ Rack QR code
![Rack QR Code](docs/img/qrcode_rack.png)
Cable QR code
-![Cable QR Code](docs/img/qrcode_cable.png)
-
-Device QR code via Jinja2 "text_template" Parameter (Multiline and labeled)
-![Cable QR Code](docs/img/qrcode_text_template.png)
\ No newline at end of file
+![Cable QR Code](docs/img/qrcode_cable.png)
\ No newline at end of file
diff --git a/docs/README_Subpages/README_Configuration.md b/docs/README_Subpages/README_Configuration.md
new file mode 100644
index 0000000..f24617b
--- /dev/null
+++ b/docs/README_Subpages/README_Configuration.md
@@ -0,0 +1,671 @@
+[<< Back to README start](/README.md)
+
+# Configuration
+The plugin is configured in the Netbox configuration file: configuration.py
+If you have followed the standard installation of Netbox, the configuration file is located under: /opt/netbox/netbox/netbox/configuration.py
+
+The following options are available. If the same variable name is specified several times in several lines, these are different examples. Entries with ‘# DEFAULT’ are system defaults.
+
+## General Plugin
+
+* `title`:
+
+ A title is displayed in the label window. This can be expanded with information. Useful if you want to provide several label variants for devices, for example.
+ ```Python
+ 'title': '', # DEFAULT
+ 'title': 'My text extension in the plugin heading.',
+ ```
+
+## Text content
+
+* `with_text`:
+
+ Text label will be added to QR code image if enabled.
+
+ ```Python
+ 'with_text': True, # DEFAULT
+ 'with_text': False,
+ ```
+
+* `text_location`:
+
+ Where to render the text, relative to the QR code.
+
+ ```Python
+ 'text_location': 'right', # DEFAULT
+ 'text_location': 'left',
+ 'text_location': 'up',
+ 'text_location': 'down',
+ ```
+
+* `text_align_horizontal`:
+
+ Defines where the text is to be displayed horizontally in the text area.
+
+ ```Python
+ 'text_align_horizontal': 'left', # DEFAULT
+ 'text_align_horizontal': 'center',
+ 'text_align_horizontal': 'right',
+ ```
+
+* `text_align_vertical`:
+
+ Defines where the text is to be displayed vertically in the text area.
+
+ ```Python
+ 'text_align_horizontal': 'middle', # DEFAULT
+ 'text_align_horizontal': 'top',
+ 'text_align_horizontal': 'bottom',
+ ```
+
+ ### Text source (Option A)
+
+* `text_fields`:
+
+ Text fields of an object that will be added as text label to QR image. It's possible to use custom field values.
+
+ ```Python
+ 'text_fields': ['name', 'serial'], # DEFAULT
+ 'text_fields': ['name'],
+ 'text_fields': ['site',
+ 'name',
+ 'id']
+ ```
+
+* `custom_text`: Additional text label to QR code image (will be added after text_fields).
+ ```Python
+ 'custom_text': None, # DEFAULT
+ 'custom_text': 'My Text',
+ ```
+ ### Text source (Option B)
+
+* `text_template`:
+
+ [Jinja2](https://jinja.palletsprojects.com/) template with {{ obj }} as context for device, rack, etc., using it ignores `text_fields` and `custom_text`.
+
+ **{{ obj.xyz }} :**
+
+ Value of the object/module (e.g. device, rack, etc.). Which values can be read depends on the Netbox module. Many names can be found during mass import, e.g. https://server/dcim/devices/import/, i.e. the “Field Options” names such as “status”, i.e. “obj.status”. Writing HTML text is permitted.
+
+ ```Python
+ # Example to output name and site in two lines with caption (See also screenshots below):
+
+ 'text_template': 'Name: {{ obj.name }}\nSite: {{ obj.site }}',
+ ```
+
+ ![Cable QR Code](/docs/img/qrcode_text_template.png)
+
+ **{{ logo }}** :
+
+ The value stored in the logo parameter.
+
+ ```Python
+
```
+ ```
+
+ **{{ qrCode }}** :
+
+ The QR code is provided as a Base64 string.
+
+ ```Python
+
+ ```
+
+
+
+## Font
+
+* `font`:
+
+ Font name for text label (All fonts supported by the browser are supported. [Web-Safe-Fonts](https://www.w3schools.com/cssref/css_websafe_fonts.php) are recommended as these are supported on all common systems without the need for subsequent installation.
+
+ ```Python
+ 'font': 'TahomaBold' # DEFAULT
+ 'font': 'Arial',
+ 'font': 'Verdana',
+ 'font': 'Arial, Verdana', # If Arial is not available then Verdana.
+ 'font': '\'Trebuchet MS\'', # If blank character in font name.
+ ```
+
+* `font_size`:
+
+ Defines the height of the font.
+
+ ```Python
+ 'font_size': '3.00mm', # DEFAULT
+ 'font_size': '0.11in', # For inches
+ ```
+
+* `font_weight`:
+
+ Determines how dense the font is.
+
+ ```Python
+ 'font_weight': 'normal', # DEFAULT
+ 'font_weight': 'bold',
+ 'font_weight': 'lighter',
+ 'font_weight': 'bolder',
+ ```
+
+* `font_color`:
+
+ Determines how dense the font is. (More Color Infos https://www.w3schools.com/html/html_colors.asp)
+
+ ```Python
+ 'font_color': 'black', # DEFAULT
+ 'font_color': 'red',
+ 'font_color': 'rgb(255, 0, 0)', # blue
+ 'font_color': '#6a5acd', # violett
+ ```
+
+## QR-Code
+
+* `with_qr`:
+
+ QR-Code label will be added to label if enabled.
+
+ ```Python
+ 'with_qr': True, # DEFAULT
+ 'with_qr': False,
+ ```
+
+ ### QR-Code alternative source
+
+ By default, the URL path to the object is used as the text for the QR code. Below is an alternative for defining your own QR code content.
+
+* `url_template`: [Jinja2](https://jinja.palletsprojects.com/) template with {{ obj }} as context for device, rack, etc.
+
+ ```Python
+ # Example to output the object name and the ID in the QR code.
+ (This means that information other than the Netbox URL can also be output in the QR code):
+
+ 'url_template': None, # DEFAULT
+ 'url_template': '{{ obj.name }} - Objekt ID: {{ obj.id }}',
+ ```
+
+ ### QR-Code Image File
+ These parameters are used to create the QR code image file.
+
+* `qr_version`:
+
+ For the image file: Parameter is an integer from 1 to 40 that controls the size of the QR Code (the smallest, version 1, is a 21x21 matrix). More Information see: [qrcode 3.0 Parameter "version"](https://pypi.org/project/qrcode/3.0/)
+
+ Experience: The higher the number, the more often it appears as if the QR codes are repeated. The value 1 is recommended for beginners.
+
+ ```Python
+ 'qr_version': 1, # DEFAULT
+ ```
+
+* `qr_error_correction`:
+
+ For the image file: This value is used to create the QR code image file. Controls the error correction used for the QR Code. More Information see: [qrcode 3.0 Parameter "error_correction"](https://pypi.org/project/qrcode/3.0/)
+
+ Experience: You can scratch x% off the QR code before it is no longer readable.
+
+ ```Python
+ 'qr_error_correction': 0, # DEFAULT - About 15% or less errors can be corrected.
+ 'qr_error_correction': 1, # About 7% or less errors can be corrected.
+ 'qr_error_correction': 2, # About 30% or less errors can be corrected.
+ 'qr_error_correction': 3, # About 25% or less errors can be corrected.
+ ```
+
+* `qr_box_size`:
+
+ For the image file: This value is used to create the QR code image file. Controls how many pixels each "Black boxes within the QR code" of the QR code is. More Information see: [qrcode 3.0 Parameter "box_size"](https://pypi.org/project/qrcode/3.0/)
+
+ Experience: The larger the value, the larger the QR code image file will be. It also takes longer to create the image file. If a value that is too small is used, the QR code may become unscaled if label_qr_width and label_qr_height have values that are too large.
+
+ ```Python
+ 'qr_box_size': 4, # DEFAULT
+ ```
+
+* `qr_border`:
+
+ For the image file: This value is used to create the QR code image file. Defines the border width when rendering the QR code image file. More Information see: [qrcode 3.0 Parameter "qr_border"](https://pypi.org/project/qrcode/3.0/)
+
+ Experience: Value 0, as the size of the QR code can be better influenced by 'label_qr_width', label_qr_height and the centered positioning creates a margin. The size of the QR code can therefore be better adjusted. However, there should be a border around the QR code on the label.
+
+ ```Python
+ 'qr_border': 0, # DEFAULT.
+ ```
+
+* `Summery qr_... `:
+
+ This table should show a few combinations of qr_[parameter name] and their resulting QR code image file sizes. With the values in column 4 you can see that you already get a 4cm x 4cm QR code image file.
+
+ | | Test | Test | Test | Test |Test | Test |Test |Test |Test | Test |
+ | ------------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
+ | qr_version | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 4 | 6 | 40 |
+ | qr_box_size | 1 | 2 | 3 | 4 | 5 | 6 | 6 | 6 | 6 | 1 |
+ | qr_error_correction | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ | qr_border | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ | DPI | 72 | 72 | 72 | 72 | 72 | 72 | 72 | 72 | 72 | 72 |
+ | cm (H/W) | `1,02` | `2,05` | `3,07` | `4,09` | `5,12` | `6,14` | `6,14` | `6,99` | `8,68` | `6,24` |
+ | Pixel (H/W) | `29` | `58` | `87` | `116` | `145` | `174` | `174` | `198` | `246` | `177` |
+
+## Label Layout
+The parameters that can be used to design the label are listed below.
+
+### Label dimensions
+* `label_width`:
+
+ Indicates how wide the physical label is.
+
+ ```Python
+ 'label_width': '56mm', # DEFAULT
+ 'label_width': '2.20in', # For inch
+ ```
+
+* `label_height`:
+
+ Indicates how high the physical label is.
+
+ ```Python
+ 'label_height': '32mm', # DEFAULT
+ 'label_height': '1.26in', # For inch
+ ```
+
+### Label edge
+* `label_edge_top`:
+
+ Indicates how high the physical label is.
+
+ ```Python
+ 'label_edge_top': '0mm', # DEFAULT
+ 'label_edge_top': '0in', # For inch
+ ```
+
+* `label_edge_left`:
+
+ Indicates how high the physical label is.
+
+ ```Python
+ 'label_edge_left': '1.5mm', # DEFAULT
+ 'label_edge_left': '0.59in', # For inch
+ ```
+
+* `label_edge_right`:
+
+ Indicates how high the physical label is.
+
+ ```Python
+ 'label_edge_right': '1.5mm', # DEFAULT
+ 'label_edge_right': '0.59in', # For inch
+ ```
+
+* `label_edge_bottom`:
+
+ Indicates how high the physical label is.
+
+ ```Python
+ 'label_edge_bottom': '0mm', # DEFAULT
+ 'label_edge_bottom': '0in', # For inch
+ ```
+
+### Label QR code positioning
+* `label_qr_width`:
+
+ Specifies how wide the QR code image should be displayed on the label.
+
+ ```Python
+ 'label_qr_width': '12mm', # DEFAULT
+ 'label_qr_width': '0.47in', # For inch
+ ```
+
+* `label_qr_height`:
+
+ Specifies how high the QR code image should be displayed on the label.
+
+ ```Python
+ 'label_qr_height': '12mm', # DEFAULT
+ 'label_qr_height': '0.47in', # For inch
+ ```
+
+* `label_qr_text_distance`:
+
+ Specifies how large the distance between the QR code and the text should be.
+
+ ```Python
+ 'label_qr_text_distance': '1mm', # DEFAULT
+ 'label_qr_text_distance': '0.039in', # For inch
+ ```
+
+## LOGO / Image
+
+* `logo`:
+
+ Enables a logo/image to be inserted in combination with the `text_template` parameter.
+
+ **Image File size:**
+
+ To keep the traffic and performance high, the image should be as small as necessary. An image with 1920x1200px and 30MB is nonsensical if it is to be 1.00x3.00cm in size at the end. The larger the image, the longer the Base64 text. If possible, the logo is completely black and not gray or colored, which makes it even smaller. (Sufficient for thermal transfer printers).
+
+ Here are a few helpful online tools:
+ Resize image online (in mm): https://image.pi7.org/resize-image-in-mm
+ Image compression (e.g. 100kb to 2kb): https://tinypng.com/
+ Convert image to Base64 string.: https://www.base64-image.de/
+
+ Your image should have the following text format at the end.
+ ```html
+ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABysAAAIDCA...
+ ```
+
+ Below is the Logo parameter for a Netbox logo. (Image specification: black/white,Background Transparent , 3,71KB, 202px x 57px, 71.26mm x 20.00mm)
+
+ It is recommended to place the Logo entry at the end of the plugin configuration, as the Base64 string can be quite long. It is also recommended to place the PLUGINS_CONFIG = {} block in Configuration.py at the end of the file.
+
+ ```Python
+ 'logo': 'data:image/png;base64,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',
+ ```
+
+ Below is how you can embed the logo in a text.
+ It is an HTML block that contains the image {{ logo }} as well as the name {{ obj.name }} and the ID of the object {{ obj.id }} in 3 lines.
+
+ ```Python
+ 'text_template': '
{{ obj.name }} Device: {{ obj.id }} ',
+ ```
+
+ If you pay attention to the proportional ratio, you can also adjust the size of the image. e.g. 5.00mm x 17.80mm. The size can also be specified in inches (in).
+ ```Python
+ 'text_template': '
{{ obj.name }} Device: {{ obj.id }} ',
+ ```
+
+## Global Configuration
+The following shows an example configuration of how to adjust parameters for all objects/modules (e.g. device, rack, etc.) at once. However, if there is a separate configuration for the device, for example, this has priority.
+
+```Python
+PLUGINS_CONFIG = {
+ 'netbox_qrcode': {
+ ##################################
+ # General Plugin
+ 'title': 'My Text in headline',
+ 'font_size': '5.12mm', # DEFAULT
+ }
+}
+```
+
+## Module-dependent configuration
+It is possible, for example, to overwrite the default values or the global settings from above for an (object/module) class such as Device. One or more parameters can also be overwritten here.
+
+Example:
+
+```Python
+PLUGINS_CONFIG = {
+ 'netbox_qrcode': {
+ ##################################
+ # General Plugin
+ 'title': 'My text for all headlines',
+ 'font_size': '5.12mm',
+ }
+ 'device': {
+ 'title': 'My text for the headline Device',
+ 'font_size': '10mm',
+ },
+}
+```
+
+**Below are the default settings of the plugin.**
+
+* `device`:
+
+ Specific label customization for the calculated https://server/dcim/devices/
+
+ ```Python
+ 'device': {
+ 'text_fields': ['name', 'serial'] # DEFAULT
+ },
+ ```
+
+* `rack`:
+
+ Specific label customization for the calculated https://server/dcim/racks/
+
+ ```Python
+ 'rack': {
+ 'text_fields': ['name'] # DEFAULT
+ },
+ ```
+
+* `cable`:
+
+ Specific label customization for the calculated https://server/dcim/cables/
+
+ ```Python
+ 'cable': {
+ 'text_fields': [
+ '_termination_a_device',
+ 'termination_a',
+ '_termination_b_device',
+ 'termination_b',
+ 'a_terminations.device',
+ 'a_terminations',
+ 'b_terminations.device',
+ 'b_terminations'
+ ] # DEFAULT
+ },
+ ```
+
+* `location`:
+
+ Specific label customization for the calculated https://server/dcim/locations/
+
+ ```Python
+ 'location': {
+ 'text_fields': ['name'] # DEFAULT
+ },
+ ```
+
+* `powerfeed`:
+
+ Specific label customization for the calculated https://server/dcim/locations/
+
+ ```Python
+ 'powerfeed': {
+ 'text_fields': ['name'], # DEFAULT
+ },
+ ```
+* `powerpanel`:
+
+ Specific label customization for the calculated https://server/dcim/locations/
+
+ ```Python
+ 'powerpanel': {
+ 'text_fields': ['name'], # DEFAULT
+ },
+ ```
+
+* `modul_X`:
+
+ It is possible to store several label layouts for an object/module (e.g. device, rack, etc.). For example, for other label information or other label sizes. To do this, an increment starting with 2 to n must be specified at the end. No numbers may be skipped in the sequence. Example: device; device_2; device_3; device_5. “device_5” is not reached because 4 is missing.
+
+ ```Python
+ 'device_2': {
+ 'title': 'My Litle Label',
+
+ 'label_width': '25mm',
+ 'label_height': '10mm',
+
+ 'font_size': '2mm',
+ 'font_weight': 'bold',
+
+ 'label_qr_width': '7.00mm',
+ 'label_qr_height': '9.00mm',
+ 'label_qr_text_distance': '0.4mm',
+
+ 'label_edge_left': '0.50mm',
+ 'label_edge_right': '0.00mm',
+
+ 'text_fields': ['name'],
+ },
+ ```
+ ```Python
+ 'device_3': {
+ ...
+ },
+ ```
+ ```Python
+ 'rack_2': {
+ ...
+ },
+ ```
+
+# Example configuration:
+
+This is a sample template of what a configuration can look like. But as I said, you do not have to specify all parameters.
+
+```Python
+PLUGINS_CONFIG = {
+ 'netbox_qrcode': {
+ ##################################
+ # General Plugin
+ 'title': '',
+
+ ##################################
+ # Text content
+ 'with_text': True,
+ 'text_location': 'right',
+ 'text_align_horizontal': 'left',
+ 'text_align_vertical': 'middle',
+
+ # Text source (Option A)
+ 'text_fields': ['name', 'serial'],
+ 'custom_text': None,
+
+ # Text source (Option B)
+ 'text_template': None,
+
+ ##################################
+ # Font
+ 'font': 'TahomaBold',
+ 'font_size': '3mm',
+ 'font_weight': 'normal',
+ 'font_color': 'black',
+
+ ##################################
+ # QR-Code
+ 'with_qr': True,
+
+ # QR-Code alternative source
+ 'url_template': None,
+
+ # QR-Code Image File
+ 'qr_version': 1,
+ 'qr_error_correction': 0,
+ 'qr_box_size': 4,
+ 'qr_border': 0,
+
+ ##################################
+ # Label Layout
+
+ # Label dimensions
+ 'label_qr_width': '12mm',
+ 'label_qr_height': '12mm',
+
+ # Label edge
+ 'label_edge_top': '0mm',
+ 'label_edge_left': '1.5mm',
+ 'label_edge_right': '1.5mm',
+ 'label_edge_bottom': '0mm',
+
+ # Label QR code positioning
+ 'label_width': '56mm',
+ 'label_height': '32mm',
+ 'label_qr_text_distance': '1mm',
+
+ ##################################
+ # Module-dependent configuration
+
+ 'device': {
+ 'text_fields': ['name', 'serial']
+ },
+
+ 'device_2': {
+ 'title': 'My Litle Label',
+
+ 'label_width': '25mm',
+ 'label_height': '10mm',
+
+ 'font_size': '2mm',
+ 'font_weight': 'bold',
+
+ 'label_qr_width': '7.00mm',
+ 'label_qr_height': '9.00mm',
+ 'label_qr_text_distance': '0.4mm',
+
+ 'label_edge_left': '0.50mm',
+ 'label_edge_right': '0.00mm',
+
+ 'text_fields': ['name'],
+ },
+
+ 'rack': {
+ 'text_fields': ['name']
+ },
+
+ 'cable': {
+ 'text_fields': [
+ '_termination_a_device',
+ 'termination_a',
+ '_termination_b_device',
+ 'termination_b',
+ 'a_terminations.device',
+ 'a_terminations',
+ 'b_terminations.device',
+ 'b_terminations'
+ ]
+ },
+
+ 'location': {
+ 'text_fields': ['name']
+ },
+
+ 'powerfeed': {
+ 'text_fields': ['name']
+ },
+
+ 'powerpanel': {
+ 'text_fields': ['name']
+ },
+
+ 'logo': ''
+ }
+}
+```
+
+## Example label configurations
+[Go to Example label configurations >>](docs/README_Subpages/README_Configuration_ExampleLabelConf.md)
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_10.png)
+
+
+# Other plugin support
+
+The following plugins are currently supported.
+
+### netbox-inventory
+
+A Netbox plugin for hardware inventory. (https://github.com/ArnesSI/netbox-inventory)
+
+* `netbox_inventory.asset`:
+
+ ```Python
+ PLUGINS_CONFIG = {
+ 'netbox_qrcode': {
+ 'netbox_inventory.asset': {
+ 'title': 'My Litle Label 1',
+ },
+ }
+ }
+ ```
+
+ ```Python
+ PLUGINS_CONFIG = {
+ 'netbox_qrcode': {
+ 'netbox_inventory.asset_2': {
+ 'title': 'My Litle Label 2',
+ },
+ }
+ }
+ ```
+
+[<< Back to README start](/README.md)
\ No newline at end of file
diff --git a/docs/README_Subpages/README_Configuration_ExampleLabelConf.md b/docs/README_Subpages/README_Configuration_ExampleLabelConf.md
new file mode 100644
index 0000000..4f5aa1c
--- /dev/null
+++ b/docs/README_Subpages/README_Configuration_ExampleLabelConf.md
@@ -0,0 +1,294 @@
+# Example label configurations
+
+## Example 1 - Default
+Standard label without customization
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_01.png)
+
+## Example 2
+QR code Higher than wide, with own logo Device name and Device ID filled with zeros.
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_02.png)
+
+```Python
+ 'device_2': {
+ 'title': 'Example',
+ 'text_template': '
{{ obj.name }} Device: {{ obj.id|stringformat:"07d" }}',
+ 'font_size': '4mm',
+ 'label_qr_width': '20mm',
+ 'label_qr_height': '30mm',
+ 'label_qr_text_distance': '2mm',
+ 'label_width': '56mm',
+ 'label_height': '32mm',
+ 'label_edge_top': '0mm',
+ 'label_edge_left': '2mm',
+ 'label_edge_right': '2mm',
+ 'logo': 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAA5CAMAAABAvUQtAAAC8VBMVEUAAAAaGhsWGyAYGx4QFBhVVVVtbm4BAwUUFhlMTk8GEh47OzzBwcEWGBu3vcPExskiJisFBgYcHR4FChBAREkYJzgOIDQFBgccHyEuNTw1Njhvb292hZUKCwwMDg8UFRYSFBYgISQtLzI+P0BodYTR1NYBAQINDxEaHB4lKCwiIyRFSEs/SFJpb3aFj5iBhIecnqBwcnWGiIswQ1l1gpCfpKnNzs/EyMvS1NcICQkNDg4ICQoREhMeHyAuLzAUFxsWGRwbHyRfYWRwdHl5foNmaWxydXh5foMGDx18ipmNjo+nqayNlJuqr7QAAQIMDQ4NDg8QERIcICQVFxkdIygpLC8vLzAxNjwDCA5CREdQU1ZZXF9DRUdscHVeX2BTVVZiY2RhY2V0dneJjI9dZW0fMUY8TFwwQ1d0fYextruVlpehoaFBVmzMz9GCjZo8TF0XFxcoKSsTFRgPERQrLC4aHR40NzoDCA01NTY9P0E+QUQYGh06PkM5Ojs4PUNDQ0RJTE8/QEFITFBQUlRFR0pAQ0YQFBhfYGNQUlY6Q0xJSktkaG02ODwdIit9f4JcYmmAhIc3QUtqa22mqKqUl5pncXtXY3Gmqa67vL1mcn+RmKBXZHO0u8FrfZCcnZ7M1+EKCgoTExIHCgwECQ4XHCAlJigeIyhGR0gtMTVAQkQfIylERkhOTU1QUVQ4PkQPEhZWWVwcKDQsMjgyPUhIUlw6Qkp9fn8VGBt3en6HiYstNT1jZGVtcXREUFx+hYxdYmdNUleFiIwqOkxfYWRATFmpqqtKVmIIGjBKV2V0eX4nPFOWnKNNXnGioqKampoACBy5vcCOk5lGW3CQkpUAAAMAAAA5OTkYICgAAAMIDRM1OT4pMjoGCQw0NjcnLDIfKzdmZWQNGyoaJjJVVVZZXWEAChYIEx+Bf31iYWAOFh8fLz9VZHRPWGFDRkpUVlmssLYMGip1dnaytbaTorMqMTiYqb09WXgAAAABAQIEBAQCAwT+4jRdAAAA93RSTlMA36OYtoaE8eWKDK4rtAYJyPnc1adTJv3QxLKDHPXw6ebZya06Evzu39HKqI5dUE5NTEI9JSQgHRn38/Ps2by1qKGLdG1pXVdXOTgWFA/39OXh4ODLxMK6uq+llouBfnt5c2dkXkM4MTAvLikfFg0I4tnXz83Jv7q4t7OzsLCrqaekopycnJeVkpGLiYd+bWpoX1VHR0VCPDc1MysjIRwO/vTv3NXS0cXCvby5t6ugoJyXk46Dfn19eHNvbmtmZGReWFhUUk5OSEVAPDk2LywqJyQSEQ/Vx8a4tbGuqaijnJubmZCOiIaFhYB5d3ZvaWdjVUQ8NjQqqSQgkwAABqJJREFUaN7d2nVYFFEQAPCxz7oDDBQVUEGxUBEVMcFE7O7u7u7u7u7u7u7u7u7WAf5yZ997xy7rHqff4bf6+4c3+x2wcy9mlgPUyt6vXHX4ZbAl77DKnv39wOhKI3EtC/rKhiNpAsYWioy7GfRY0iHTFgytIXK5Qc9n5BKCod1DbjvoGYecGxjaFuQ+gJ4pyG0AQyuL3ALQ4xe5Bo1tOMoagJ42HshkBKMLLojo0Rj0nHeWskiHGPgUHCvn482bn7QEh+pr62xqS5lkCz2duxw42COUfAKHSoo4RjeTgjG2suJTKinAoYoi1rOVSWIeGDOV0IM737eJJpUc4/ccDlRUE2OmktOdH1r6C+y8i+PrYosykisOTeUCorI/LBYW1lDTdxVAWdhAcJzVKGnu0FR6IRMWFFsSVCkioktstaCuyEQsAMdJjpI8Dk2lAtqv1P+TSklwnCEoaenQVGogVzSupGjm8PDKt+OqFF2KXBu79vPkA8faQRT+J0pOPJYWFLKhZIaI0lBURhrMnrzv0GzQ8Jq8b/8MRWEWP0p1RbSQjfi2j4jQdGDlwu3ouzquqFKlynjwTUWvDL/7AxSKZ0D5ak1fFu8xmUzyUWLykUYtRCotYVcqJIXrg9Kc4SYk6e6UBsacrYDJ5OnSngUZPE2mTPQtTZAMjWxc4kFU0+RHx15gSyJ6yZsQyppk+grCzPRoNRLIc1Q6yRdYphx1UEjfGqzGYqTe7UGWRI4yAKlNw0Bv+ThuuHGcn+3GZUEhxMFgO5UEiJjaHYXFC4E5TpE6l9eqS81FKosUF53zAVcblTwDQDZVjiZIo6byiF6u7cESglZhxMZ2pEIC+dP/W+X7ly3HjByD5FEuAHihSSWNCFwr8nmtCsxQXggqLlJfD+YZ5EfSFOxOJRatO3tSWXPOu9wR+W5ugkxeXdMi30kX2qJeXiE1Kdgf4uXl1SEylfSl05aff8BDHpdgq1MeFyzhXz5tTrbjgoHpJi849iUbOD6VlUA+0rCiRd5mNHwJzA4KzirebX7SiVT6sGChfM+ZgfSgoU+AOPWINwvaO1OQRT49IAZS+c4C+i3h88VK9wAhnB+VokSesdYV1R15V6RwjjTKq94InZWFOhcKrWMglUI8oPcq7CKNqtItbtuaXTY6kxQN0FR7MSu7QdhE4UTqyGmwHmRiiycXUV1kdkEMpNKVB2solZRUbQpiVE66jctpEJpROFoavKPBQRAuh/EfIN4xshZiIpVkPLglUrmm7YuS6abSEoRTFD6UBttpcASEK65SmEpESTzZWREQk6nUss7KEjpgUWmpbip+2llpzFaa4E9hdRFlFvU0JlPpKVIBH/pV+ZNw7S8lSTJPd9vvAKGOaF5LqVfQbgqHaGpn3b8xKzCIKrcZtNajpIVq2wdaeJTPlZ9gvADOirwNCW/EJtC4QB1Wd2N8VkSJWw1Ma49nIDxQ3UJ81lOxkjHPJ7Ku9KGhOzttLXKRCVuo6CKKQ2+5FwgArb4OnhWQy92AvNTBNo1AdJun/Pv0yrxgDmnHUiHuxVv5h9TPxPorccdkrJd/qxKd+N3L5C3fTTytZwGtYogNHZpKAD+Ch/QzoWhcSBN2vYoHppAXmEBVVPm6serr4qYHyRPkbW0sg0GjO7XAtlPJPX7nUTsXGJnljApLvgCTX9MZe3bGSIUC1IVQWG4BMkmxRYL5WM37BtWg/uZfpfKKD/ujJGsoRHGNLifgwXUKLvLgUg+0qpkfhPrK55WRNEhbB4VViqa9RGa02qR8cKirqpSzNL08WQdRdbY2+etQFssCah1rpk6degMPtqaWtAPhcL9C8kbu10z1bLksjHasz1x6l6s5Oa2Q7rp6ONWhVZNAKXRbNVea5ljDeCtqHrDMyalaH+DyV5e+u8so7aeqpFgclRFxFiN2HTFCGhb7sz9ZdJjtm/tcB4hi7gnf6XNBxf+Ur19a0Jg/3Xd6K/gNQWi/IDC0OGi/jWBoOZErMjCxUsaM6RBdMrq5uSUugtxeMDKzuM8aEJWL9ZGpBj8sy4ORpRJzYtGtKyLfwnnByCiT6s3qJZwSTYk8Wm/cITA0yiQrEL1U/hVZbWUCPv9IKh1aXbVoM9Fue+Mb5o7uleiZ2Qx6RjkjuuQEo1uOTHdzdJ+MGT2XBsh4gK4cyDgbu5ZAZWTSXY3+06QpYGgVkPumf0z/G80KFEauHOhx+0f+capU9P8V5YdMJzC4geyp0NaWHoXEtQ0YXcnulboktNieOqdKnQYbu4ME+AnhAIW2MwgdrwAAAABJRU5ErkJggg==',
+ },
+```
+## Example 3
+Text left QR code right with distance to the edge.
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_03.png)
+
+```Python
+ 'device_2': {
+ 'title': 'Example',
+ 'font_size': '4mm',
+ 'label_qr_width': '15mm',
+ 'label_qr_height': '15mm',
+ 'label_qr_text_distance': '2mm',
+ 'label_width': '56mm',
+ 'label_height': '32mm',
+ 'label_edge_top': '0mm',
+ 'label_edge_left': '2mm',
+ 'label_edge_right': '2mm',
+ 'text_location': 'left',
+ },
+```
+
+## Example 4
+Center text only
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_04.png)
+
+```Python
+ 'device_2': {
+ 'title': 'Example',
+ 'font_size': '4mm',
+ 'text_align_horizontal': 'center',
+ 'text_align_vertical': 'middle',
+ 'label_qr_width': '20mm',
+ 'label_qr_height': '20mm',
+ 'label_qr_text_distance': '0mm',
+ 'label_width': '56mm',
+ 'label_height': '32mm',
+ 'label_edge_top': '0mm',
+ 'label_edge_left': '0mm',
+ 'label_edge_right': '0mm',
+ 'with_text': True,
+ 'with_qr': False,
+ },
+```
+
+## Example 5
+Text links only
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_05.png)
+
+```Python
+ 'device_2': {
+ 'title': 'Example',
+ 'font_size': '4mm',
+ 'text_align_horizontal': 'left',
+ 'text_align_vertical': 'middle',
+ 'label_qr_width': '20mm',
+ 'label_qr_height': '20mm',
+ 'label_qr_text_distance': '0mm',
+ 'label_width': '56mm',
+ 'label_height': '32mm',
+ 'label_edge_top': '0mm',
+ 'label_edge_left': '2mm',
+ 'label_edge_right': '0mm',
+ 'with_text': True,
+ 'with_qr': False,
+ },
+```
+
+## Example 6
+QR code only
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_06.png)
+
+```Python
+ 'device_2': {
+ 'title': 'Example',
+ 'font_size': '4mm',
+ 'label_qr_width': '20mm',
+ 'label_qr_height': '20mm',
+ 'label_qr_text_distance': '0mm',
+ 'label_width': '56mm',
+ 'label_height': '32mm',
+ 'label_edge_top': '0mm',
+ 'label_edge_left': '0mm',
+ 'label_edge_right': '0mm',
+ 'with_text': False,
+ 'with_qr': True,
+ },
+```
+
+## Example 7
+Upright, large font with line break and serial number
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_07.png)
+
+```Python
+ 'device_2': {
+ 'title': 'Example',
+ 'font_size': '4mm',
+ 'label_qr_width': '20mm',
+ 'label_qr_height': '20mm',
+ 'label_qr_text_distance': '0mm',
+ 'label_width': '32mm',
+ 'label_height': '56mm',
+ 'label_edge_top': '2mm',
+ 'label_edge_left': '0mm',
+ 'label_edge_right': '0mm',
+ 'text_location': 'up',
+ 'text_align_horizontal': 'center',
+ 'text_align_vertical': 'top',
+ 'label_edge_bottom': '2mm',
+ },
+```
+
+## Example 8
+Upright, large font with line break and serial number
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_08.png)
+
+```Python
+ 'device_2': {
+ 'title': 'Example',
+ 'font_size': '4mm',
+ 'label_qr_width': '20mm',
+ 'label_qr_height': '20mm',
+ 'label_qr_text_distance': '2mm',
+ 'label_width': '32mm',
+ 'label_height': '56mm',
+ 'label_edge_top': '2mm',
+ 'label_edge_left': '0mm',
+ 'label_edge_right': '0mm',
+ 'text_location': 'down',
+ 'text_align_horizontal': 'center',
+ 'text_align_vertical': 'top',
+ },
+```
+
+## Example 9
+Small label
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_09.png)
+
+```Python
+ 'device_2': {
+ 'title': 'Example',
+ 'font_size': '4mm',
+ 'label_qr_width': '20mm',
+ 'label_qr_height': '20mm',
+ 'label_qr_text_distance': '2mm',
+ 'label_width': '32mm',
+ 'label_height': '56mm',
+ 'label_edge_top': '2mm',
+ 'label_edge_left': '0mm',
+ 'label_edge_right': '0mm',
+ 'text_location': 'down',
+ },
+```
+
+## Example 10 - Completely self-designed
+
+This way, many label design options should be possible. The design of the label content is completely specified by the user via this method.
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_10.png)
+
+```Python
+ 'device_2': {
+ 'with_qr': False,
+ 'text_align_horizontal': 'center',
+ 'text_align_vertical': 'middle',
+ 'title': 'Example',
+ 'text_template': '
'
+ '{{ obj.name }} '
+ '
'
+ 'Device: {{ obj.id|stringformat:"07d" }}'
+ '
😝 My label design 😝
',
+
+ 'label_width': '56mm',
+ 'label_height': '32mm',
+ 'label_edge_top': '0mm',
+ 'label_edge_left': '0mm',
+ 'label_edge_right': '0mm',
+ },
+```
+
+## Example 11 - Cable Label vertical writing.
+
+This example shows how to write vertically, e.g. for cable labeling on a wide but not so high single label.
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_11.png)
+
+```Python
+ 'cable': {
+ 'title': 'Für Kabel',
+ 'with_qr': False,
+ 'label_edge_left': '0.00mm',
+ 'label_edge_right': '0.00mm',
+ 'label_edge_top': '0.00mm',
+ 'text_align_vertical': 'middle',
+ 'text_align_horizontal': 'center',
+ 'text_template': ''
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ '{{ obj.label }}'
+ ''
+ },
+```
+
+## Example 12 - Cable Label vertical writing.
+
+This example shows the creation of a Cabel label with barcode 128. Please note that an online function is used here (internet may be necessary). Barcode 128 is not created on the Netbox server.
+
+![Cable QR Code](/docs/img/Configuration_Label_Example_12.png)
+
+```Python
+ 'cable_2': {
+ 'title': 'Für Kabel',
+ 'with_qr': False,
+ 'label_edge_left': '0.00mm',
+ 'label_edge_right': '0.00mm',
+ 'label_edge_top': '0.00mm',
+ 'text_align_vertical': 'middle',
+ 'text_align_horizontal': 'center',
+
+ # QR-Code Image File
+ 'qr_version': 1,
+ 'qr_error_correction': 1,
+ 'qr_box_size': 2,
+ 'qr_border': 0,
+
+ 'text_template': ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+```
\ No newline at end of file
diff --git a/docs/img/Configuration_Browser_Print_Settings.png b/docs/img/Configuration_Browser_Print_Settings.png
new file mode 100644
index 0000000..b767a4f
Binary files /dev/null and b/docs/img/Configuration_Browser_Print_Settings.png differ
diff --git a/docs/img/Configuration_Label_Example_01.png b/docs/img/Configuration_Label_Example_01.png
new file mode 100644
index 0000000..2e406ea
Binary files /dev/null and b/docs/img/Configuration_Label_Example_01.png differ
diff --git a/docs/img/Configuration_Label_Example_02.png b/docs/img/Configuration_Label_Example_02.png
new file mode 100644
index 0000000..92ee978
Binary files /dev/null and b/docs/img/Configuration_Label_Example_02.png differ
diff --git a/docs/img/Configuration_Label_Example_03.png b/docs/img/Configuration_Label_Example_03.png
new file mode 100644
index 0000000..43d5ae7
Binary files /dev/null and b/docs/img/Configuration_Label_Example_03.png differ
diff --git a/docs/img/Configuration_Label_Example_04.png b/docs/img/Configuration_Label_Example_04.png
new file mode 100644
index 0000000..8573cc3
Binary files /dev/null and b/docs/img/Configuration_Label_Example_04.png differ
diff --git a/docs/img/Configuration_Label_Example_05.png b/docs/img/Configuration_Label_Example_05.png
new file mode 100644
index 0000000..f221a8a
Binary files /dev/null and b/docs/img/Configuration_Label_Example_05.png differ
diff --git a/docs/img/Configuration_Label_Example_06.png b/docs/img/Configuration_Label_Example_06.png
new file mode 100644
index 0000000..ec04bc5
Binary files /dev/null and b/docs/img/Configuration_Label_Example_06.png differ
diff --git a/docs/img/Configuration_Label_Example_07.png b/docs/img/Configuration_Label_Example_07.png
new file mode 100644
index 0000000..58df97e
Binary files /dev/null and b/docs/img/Configuration_Label_Example_07.png differ
diff --git a/docs/img/Configuration_Label_Example_08.png b/docs/img/Configuration_Label_Example_08.png
new file mode 100644
index 0000000..35211c2
Binary files /dev/null and b/docs/img/Configuration_Label_Example_08.png differ
diff --git a/docs/img/Configuration_Label_Example_09.png b/docs/img/Configuration_Label_Example_09.png
new file mode 100644
index 0000000..18f2376
Binary files /dev/null and b/docs/img/Configuration_Label_Example_09.png differ
diff --git a/docs/img/Configuration_Label_Example_10.png b/docs/img/Configuration_Label_Example_10.png
new file mode 100644
index 0000000..33897e4
Binary files /dev/null and b/docs/img/Configuration_Label_Example_10.png differ
diff --git a/docs/img/Configuration_Label_Example_11.png b/docs/img/Configuration_Label_Example_11.png
new file mode 100644
index 0000000..4edaca5
Binary files /dev/null and b/docs/img/Configuration_Label_Example_11.png differ
diff --git a/docs/img/Configuration_Label_Example_12.png b/docs/img/Configuration_Label_Example_12.png
new file mode 100644
index 0000000..8585935
Binary files /dev/null and b/docs/img/Configuration_Label_Example_12.png differ
diff --git a/docs/img/Configuration_Printer_WordPreview.png b/docs/img/Configuration_Printer_WordPreview.png
new file mode 100644
index 0000000..ca7045d
Binary files /dev/null and b/docs/img/Configuration_Printer_WordPreview.png differ
diff --git a/docs/img/Configuration_Printer_ZM400.png b/docs/img/Configuration_Printer_ZM400.png
new file mode 100644
index 0000000..d904fd3
Binary files /dev/null and b/docs/img/Configuration_Printer_ZM400.png differ
diff --git a/netbox_qrcode/__init__.py b/netbox_qrcode/__init__.py
index 6d16a96..d525620 100644
--- a/netbox_qrcode/__init__.py
+++ b/netbox_qrcode/__init__.py
@@ -11,21 +11,72 @@ class QRCodeConfig(PluginConfig):
author_email = 'mgk.kolek@gmail.com'
required_settings = []
default_settings = {
+
+ ##################################
+ # General Plugin
+ 'title': '',
+
+ ##################################
+ # Text content
'with_text': True,
+ 'text_location': 'right',
+ 'text_align_horizontal': 'left',
+ 'text_align_vertical': 'middle',
+
+ # Text source (Option A)
'text_fields': ['name', 'serial'],
- 'font': 'TahomaBold',
'custom_text': None,
- 'text_location': 'right',
+
+ # Text source (Option B)
+ 'text_template': None,
+
+ ##################################
+ # Font
+ 'font': 'TahomaBold',
+ 'font_size': '3mm',
+ 'font_weight': 'normal',
+ 'font_color': 'black',
+
+ ##################################
+ # QR-Code
+ 'with_qr': True,
+
+ # QR-Code alternative source
+ 'url_template': None,
+
+ # QR-Code Image File
'qr_version': 1,
'qr_error_correction': 0,
- 'qr_box_size': 6,
- 'qr_border': 4,
+ 'qr_box_size': 4,
+ 'qr_border': 0,
+
+ ##################################
+ # Label Layout
+
+ # Label dimensions
+ 'label_qr_width': '12mm',
+ 'label_qr_height': '12mm',
+
+ # Label edge
+ 'label_edge_top': '0mm',
+ 'label_edge_left': '1.5mm',
+ 'label_edge_right': '1.5mm',
+ 'label_edge_bottom': '0mm',
+
+ # Label QR code positioning
+ 'label_width': '56mm',
+ 'label_height': '32mm',
+ 'label_qr_text_distance': '1mm',
+
+ # Module-dependent configuration
'device': {
'text_fields': ['name', 'serial']
},
+
'rack': {
'text_fields': ['name']
},
+
'cable': {
'text_fields': [
'_termination_a_device',
@@ -38,15 +89,20 @@ class QRCodeConfig(PluginConfig):
'b_terminations'
]
},
+
'location': {
'text_fields': ['name']
},
+
'powerfeed': {
- 'text_fields': ['name'],
+ 'text_fields': ['name']
},
+
'powerpanel': {
'text_fields': ['name']
- }
+ },
+
+ 'logo': '',
}
config = QRCodeConfig # noqa E305
diff --git a/netbox_qrcode/fonts/ArialBlack.ttf b/netbox_qrcode/fonts/ArialBlack.ttf
deleted file mode 100644
index 8877277..0000000
Binary files a/netbox_qrcode/fonts/ArialBlack.ttf and /dev/null differ
diff --git a/netbox_qrcode/fonts/ArialMT.ttf b/netbox_qrcode/fonts/ArialMT.ttf
deleted file mode 100644
index 084f062..0000000
Binary files a/netbox_qrcode/fonts/ArialMT.ttf and /dev/null differ
diff --git a/netbox_qrcode/fonts/ComicSansMSBold.ttf b/netbox_qrcode/fonts/ComicSansMSBold.ttf
deleted file mode 100644
index e68979c..0000000
Binary files a/netbox_qrcode/fonts/ComicSansMSBold.ttf and /dev/null differ
diff --git a/netbox_qrcode/fonts/CourierNewBold.ttf b/netbox_qrcode/fonts/CourierNewBold.ttf
deleted file mode 100644
index 894c455..0000000
Binary files a/netbox_qrcode/fonts/CourierNewBold.ttf and /dev/null differ
diff --git a/netbox_qrcode/fonts/Tahoma.ttf b/netbox_qrcode/fonts/Tahoma.ttf
deleted file mode 100644
index d204f95..0000000
Binary files a/netbox_qrcode/fonts/Tahoma.ttf and /dev/null differ
diff --git a/netbox_qrcode/fonts/TahomaBold.ttf b/netbox_qrcode/fonts/TahomaBold.ttf
deleted file mode 100644
index e4024e2..0000000
Binary files a/netbox_qrcode/fonts/TahomaBold.ttf and /dev/null differ
diff --git a/netbox_qrcode/template_content.py b/netbox_qrcode/template_content.py
index d4b44ba..df9c173 100644
--- a/netbox_qrcode/template_content.py
+++ b/netbox_qrcode/template_content.py
@@ -1,124 +1,166 @@
from packaging import version
-
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
-from django.template import engines
-
from netbox.plugins import PluginTemplateExtension
+from .template_content_functions import create_text, create_url, config_for_modul, create_QRCode
-from .utilities import get_img_b64, get_qr, get_qr_text, get_concat
-
+# ******************************************************************************************
+# Contains the main functionalities of the plugin and thus creates the content for the
+# individual modules, e.g: Device, Rack etc.
+# ******************************************************************************************
+##################################
+# Class for creating the plugin content
class QRCode(PluginTemplateExtension):
- def x_page(self):
- config = self.context['config']
- obj = self.context['object']
- request = self.context['request']
- url = request.build_absolute_uri(obj.get_absolute_url())
- # get object settings
- obj_cfg = config.get(self.model.replace('dcim.', ''))
- if obj_cfg is None:
- return ''
- # and ovverride default
- config.update(obj_cfg)
-
- qr_args = {}
- for k, v in config.items():
- if k.startswith('qr_'):
- qr_args[k.replace('qr_', '')] = v
-
- qr_img = get_qr(url, **qr_args)
- if config.get('with_text'):
- if config.get('text_template'):
- django_engine = engines["django"]
- template = django_engine.from_string(config.get('text_template'))
- text = template.render({'obj': obj})
- else:
- text = []
- for text_field in config.get('text_fields', []):
- cfn = None
- if '.' in text_field:
- try:
- text_field, cfn = text_field.split('.')
- except ValueError:
- cfn = None
- if getattr(obj, text_field, None):
- if cfn:
- try:
- if getattr(obj, text_field).get(cfn):
- text.append('{}'.format(getattr(obj, text_field).get(cfn)))
- except AttributeError:
- # fix for nb3.3: trying to get cable termination and device in same way as custom field
- if type(getattr(obj, text_field)) is list:
- first_element = next(iter(getattr(obj, text_field)), None)
- if first_element and getattr(first_element, cfn, None):
- text.append('{}'.format(getattr(first_element, cfn)))
- else:
- text.append('{}'.format(getattr(obj, text_field)))
- custom_text = config.get('custom_text')
- if custom_text:
- text.append(custom_text)
- text = '\n'.join(text)
- text_img = get_qr_text(qr_img.size, text, config.get('font'), config.get('font_size', 0))
- qr_with_text = get_concat(qr_img, text_img, config.get('text_location', 'right'))
-
- img = get_img_b64(qr_with_text)
- else:
- img = get_img_b64(qr_img)
+ ##################################
+ # Creates a plug-in view for a label.
+ # --------------------------------
+ # Parameter:
+ # labelDesignNo: Which label design should be loaded.
+ def Create_SubPluginContent(self, labelDesignNo):
+
+ thisSelf = self
+
+ obj = self.context['object'] # An object of the type Device, Rack etc.
+
+ # Config suitable for the module
+ config = config_for_modul(thisSelf, labelDesignNo)
+
+ # Abort if no config data.
+ if config is None:
+ return ''
+
+ # Get URL for QR code
+ url = create_url(thisSelf, config, obj)
+
+ # Create a QR code
+ qrCode = create_QRCode(url, config)
+
+ # Create the text for the label if required.
+ text = create_text(config, obj, qrCode)
+
+ # Create plugin using template
try:
if version.parse(settings.VERSION).major >= 3:
- return self.render(
- 'netbox_qrcode/qrcode3.html', extra_context={'image': img}
+
+ render = self.render(
+ 'netbox_qrcode/qrcode3.html', extra_context={
+ 'title': config.get('title'),
+ 'labelDesignNo': labelDesignNo,
+ 'qrCode': qrCode,
+ 'with_text': config.get('with_text'),
+ 'text': text,
+ 'text_location': config.get('text_location'),
+ 'text_align_horizontal': config.get('text_align_horizontal'),
+ 'text_align_vertical': config.get('text_align_vertical'),
+ 'font': config.get('font'),
+ 'font_size': config.get('font_size'),
+ 'font_weight': config.get('font_weight'),
+ 'font_color': config.get('font_color'),
+ 'with_qr': config.get('with_qr'),
+ 'label_qr_width': config.get('label_qr_width'),
+ 'label_qr_height': config.get('label_qr_height'),
+ 'label_qr_text_distance': config.get('label_qr_text_distance'),
+ 'label_width': config.get('label_width'),
+ 'label_height': config.get('label_height'),
+ 'label_edge_top': config.get('label_edge_top'),
+ 'label_edge_left': config.get('label_edge_left'),
+ 'label_edge_right': config.get('label_edge_right'),
+ 'label_edge_bottom': config.get('label_edge_bottom')
+ }
)
+
+ return render
else:
+ # Versions 1 and 2 are no longer supported.
return self.render(
- 'netbox_qrcode/qrcode.html', extra_context={'image': img}
+ 'netbox_qrcode/qrcode.html', extra_context={'image': qrCode}
)
except ObjectDoesNotExist:
return ''
+ ##################################
+ # Create plugin content
+ # - First, a plugin view is created for the first label.
+ # - If there are further configuration entries for the object/model (e.g. device, rack etc.),
+ # further label views are also created as additional plugin views.
+ def Create_PluginContent(self):
+ # First Plugin Content
+ pluginContent = QRCode.Create_SubPluginContent(self, 1)
+
+ # Check whether there is another configuration for the object, e.g. device, rack, etc.
+ # Support up to 10 additional label configurations (objectName_2 to ..._10) per object (e.g. device, rack, etc.).
+
+ config = self.context['config'] # Django configuration
+
+ for i in range(2, 11):
+
+ configName = self.model.replace('dcim.', '') + '_' + str(i)
+ obj_cfg = config.get(configName) # Load configuration for additional label if possible.
+
+ if(obj_cfg):
+ pluginContent += QRCode.Create_SubPluginContent(self, i) # Add another plugin view
+ else:
+ break
+
+ return pluginContent
+
+##################################
+# The following section serves to integrate the plugin into Netbox Core.
+
+# Class for creating a QR code for the model: Device
class DeviceQRCode(QRCode):
- model = 'dcim.device'
+ model = 'dcim.device' # Info for Netbox in which model the plugin should be integrated.
def right_page(self):
- return self.x_page()
-
+ return self.Create_PluginContent()
+# Class for creating a QR code for the model: Rack
class RackQRCode(QRCode):
- model = 'dcim.rack'
+ model = 'dcim.rack' # Info for Netbox in which model the plugin should be integrated.
def right_page(self):
- return self.x_page()
-
+ return self.Create_PluginContent()
+# Class for creating a QR code for the model: Cable
class CableQRCode(QRCode):
- model = 'dcim.cable'
+ model = 'dcim.cable' # Info for Netbox in which model the plugin should be integrated.
def left_page(self):
- return self.x_page()
-
+ return self.Create_PluginContent()
+# Class for creating a QR code for the model: Location
class LocationQRCode(QRCode):
- model = 'dcim.location'
+ model = 'dcim.location' # Info for Netbox in which model the plugin should be integrated.
def left_page(self):
- return self.x_page()
-
+ return self.Create_PluginContent()
+# Class for creating a QR code for the model: Power Feed
class PowerFeedQRCode(QRCode):
- model = 'dcim.powerfeed'
+ model = 'dcim.powerfeed' # Info for Netbox in which model the plugin should be integrated.
def right_page(self):
- return self.x_page()
-
+ return self.Create_PluginContent()
+# Class for creating a QR code for the model: Power Panel
class PowerPanelQRCode(QRCode):
- model = 'dcim.powerpanel'
+ model = 'dcim.powerpanel' # Info for Netbox in which model the plugin should be integrated.
def right_page(self):
- return self.x_page()
+ return self.Create_PluginContent()
+##################################
+# Other plugins support
+
+# Class for creating a QR code for the Plugin: Netbox-Inventory (https://github.com/ArnesSI/netbox-inventory)
+class Plugin_Netbox_Inventory(QRCode):
+ model = 'netbox_inventory.asset' # Info for Netbox in which model the plugin should be integrated.
+
+ def right_page(self):
+ return self.Create_PluginContent()
-template_extensions = [DeviceQRCode, RackQRCode, CableQRCode, LocationQRCode, PowerFeedQRCode, PowerPanelQRCode]
+# Connects Netbox Core with the plug-in classes
+template_extensions = [DeviceQRCode, RackQRCode, CableQRCode, LocationQRCode, PowerFeedQRCode, PowerPanelQRCode, Plugin_Netbox_Inventory]
\ No newline at end of file
diff --git a/netbox_qrcode/template_content_functions.py b/netbox_qrcode/template_content_functions.py
new file mode 100644
index 0000000..e9edfb9
--- /dev/null
+++ b/netbox_qrcode/template_content_functions.py
@@ -0,0 +1,146 @@
+from .utilities import get_img_b64, get_qr
+from django.template import engines
+
+# ******************************************************************************************
+# For better clarity, the sub-functions of template_content.py have been outsourced.
+# ******************************************************************************************
+
+##################################
+# The configuration is taken and all fields that are module-specific (e.g. Device, Rack, etc.) are replaced.
+# --------------------------------
+# Parameter:
+# labelDesignNo: Which label design should be loaded.
+# parentSelf: Self from Parrent Function
+def config_for_modul(parentSelf, labelDesignNo):
+
+ # Copy so that the Runtime data is not changed.
+ config = parentSelf.context['config'].copy() # From Netbox Config File
+
+ # Create suffix to read the correct module configuration.
+ confModulsufix = str() # None if the first standard label
+
+ if(labelDesignNo >= 2):
+ confModulsufix = '_' + str(labelDesignNo)
+
+ # Collect the QR code plugin configuration for the specific object such as device, rack etc.
+ # and overwrite the default configuration fields.
+ obj_cfg = config.get(parentSelf.model.replace('dcim.', '') + confModulsufix) # get spezific object settings
+
+ if obj_cfg is not None:
+ config.update(obj_cfg) # Ovverride default confiv Values
+ return config
+ else:
+ return config # No module customisation
+
+##################################
+# Create QR-Code
+# --------------------------------
+# Parameter:
+# text: Text for QR-Code
+# config: From the Netbox configuration file
+def create_QRCode(text, config):
+
+ # Collect the configuration entries that begin with "qr_.
+ # These are required to generate the QR code.
+ qr_args = {}
+ for k, v in config.items():
+ if k.startswith('qr_'):
+ qr_args[k.replace('qr_', '')] = v
+
+ # Create a QR code
+ qrCode = get_qr(text, **qr_args)
+ return get_img_b64(qrCode)
+
+
+##################################
+# Create URL for QR code
+# --------------------------------
+# Parameter:
+# config: From the Netbox configuration file
+# obj: Data from the model (e.g. device, rack, etc.)
+# request: HTML Request Information
+def create_url(parentSelf, config, obj):
+
+ request = parentSelf.context['request'] # HTML Request Informations
+
+ if config.get('url_template'):
+ # A user-defined design specification of the URL is provided in ninja2 format.
+ django_engine = engines["django"]
+ template = django_engine.from_string(config.get('url_template')) # Custom template for URL design.
+ return template.render({'obj': obj}) # Replace placeholder
+ else:
+ return request.build_absolute_uri(obj.get_absolute_url()) # URL to the requested page
+
+##################################
+# Create text for label
+# --------------------------------
+# Parameter:
+# config: From the Netbox configuration file
+# obj: Data from the model (e.g. device, rack, etc.)
+# qrCode: QR-Code Image
+def create_text(config, obj, qrCode):
+
+ text = str()
+
+ if config.get('with_text'):
+ if config.get('text_template'):
+ return get_text_template(config, obj, qrCode) # Create text content based on the Ninja2 template from the user
+ else:
+ return get_text_fields(config, obj) # Use the list of variables from the Config.
+
+##################################
+# A user-defined design specification of the text is provided in ninja2 format.
+# --------------------------------
+# Parameter:
+# config: From the Netbox configuration file
+# obj: Data from the model (e.g. device, rack, etc.)
+# qrCode: QR-Code Image (To create a freely defined label with QR code.)
+def get_text_template(config, obj, qrCode):
+
+ django_engine = engines["django"]
+ template = django_engine.from_string(config.get('text_template')) # Get Custom Template
+ logo = config.get('logo')
+ return template.render({'obj': obj,
+ 'logo': logo,
+ 'qrCode': qrCode}) # Replace placeholder
+
+##################################
+# Retrieves all values from the object (e.g. device, rack, etc.)
+# depending on the configuration parameter that are to be displayed in list form and prepares them.
+# --------------------------------
+# Parameter:
+# config: From the Netbox configuration file
+# obj: Data from the model (e.g. device, rack, etc.)
+def get_text_fields(config, obj):
+
+ text = []
+
+ for text_field in config.get('text_fields', []):
+ cfn = None
+ if '.' in text_field:
+ try:
+ text_field, cfn = text_field.split('.')
+ except ValueError:
+ cfn = None
+ if getattr(obj, text_field, None):
+ if cfn:
+ try:
+ if getattr(obj, text_field).get(cfn):
+ text.append('{}'.format(getattr(obj, text_field).get(cfn)))
+ except AttributeError:
+ # fix for nb3.3: trying to get cable termination and device in same way as custom field
+ if type(getattr(obj, text_field)) is list:
+ first_element = next(iter(getattr(obj, text_field)), None)
+ if first_element and getattr(first_element, cfn, None):
+ text.append('{}'.format(getattr(first_element, cfn)))
+ else:
+ text.append('{}'.format(getattr(obj, text_field)))
+
+ # Append user-defined text to the end.
+ custom_text = config.get('custom_text')
+
+ if custom_text:
+ text.append(custom_text)
+
+ # Convert text list to string with line breaks.
+ return ' '.join(text)
\ No newline at end of file
diff --git a/netbox_qrcode/templates/netbox_qrcode/qrcode3.html b/netbox_qrcode/templates/netbox_qrcode/qrcode3.html
index 88d4629..79e96b4 100644
--- a/netbox_qrcode/templates/netbox_qrcode/qrcode3.html
+++ b/netbox_qrcode/templates/netbox_qrcode/qrcode3.html
@@ -1,19 +1,165 @@
+
+
+
- QR Code
+ OR-Code (H/W: {{label_height}} x {{label_width}}) {% if title %} - {{title}}{% endif %}
-
+
+
+
+ {# Only Text label #}
+ {% if with_text is True and with_qr is False %}
+
+
+
+ {{text|safe|escape}}
+
+
+
+ {% endif %}
+
+ {# Text and QR-Code #}
+ {% if with_text is True and with_qr is True %}
+
+ {# Horizontal label #}
+ {% if text_location == "right" or text_location == "left" %}
+
+
+
+ {% if text_location == "right" %}
+
+ {% include "netbox_qrcode/qrcode3_sub_qrcode.html" %}
+
+ {% endif %}
+
+
+
+
+ {{text|safe|escape}}
+
+
+
+
+ {% if text_location == "left" %}
+
+ {% include "netbox_qrcode/qrcode3_sub_qrcode.html" %}
+
+ {% endif %}
+
+
+
+ {% endif %}
+
+ {# Vertical label #}
+ {% if with_qr and text_location == "up" or text_location == "down" %}
+
+
+ {% if text_location == "down" %}
+
+
+ {% include "netbox_qrcode/qrcode3_sub_qrcode.html" %}
+
+
+ {% endif %}
+
+
+
+
+
+ {{text|safe|escape}}
+
+
+
+
+
+ {% if text_location == "up" %}
+
+
+ {% include "netbox_qrcode/qrcode3_sub_qrcode.html" %}
+
+
+ {% endif %}
+
+
+ {% endif %}
+ {% endif %}
+
+ {# Only QR-Code label #}
+ {% if with_text is False and with_qr is True %}
+
+ {% include "netbox_qrcode/qrcode3_sub_qrcode.html" %}
+
+ {% endif %}
+
+
+
diff --git a/netbox_qrcode/templates/netbox_qrcode/qrcode3_sub_qrcode.html b/netbox_qrcode/templates/netbox_qrcode/qrcode3_sub_qrcode.html
new file mode 100644
index 0000000..1c14039
--- /dev/null
+++ b/netbox_qrcode/templates/netbox_qrcode/qrcode3_sub_qrcode.html
@@ -0,0 +1,13 @@
+
+
+
\ No newline at end of file
diff --git a/netbox_qrcode/utilities.py b/netbox_qrcode/utilities.py
index c1e2f7c..e0cd376 100644
--- a/netbox_qrcode/utilities.py
+++ b/netbox_qrcode/utilities.py
@@ -1,18 +1,17 @@
import base64
import qrcode
-
from io import BytesIO
-from PIL import Image, ImageFont, ImageDraw
-
-from pkg_resources import resource_stream
-
-
-def get_qr_with_text(qr, descr):
- dsi = get_qr_text(qr.size, descr)
- resimg = get_concat(qr, dsi)
- return get_img_b64(resimg)
+# ******************************************************************************************
+# Includes useful tools to create the content.
+# ******************************************************************************************
+##################################
+# Creates a QR code as an image.: https://pypi.org/project/qrcode/3.0/
+# --------------------------------
+# Parameter:
+# text: Text to be included in the QR code.
+# **kwargs: List of parameters which properties the QR code should have. (e.g. version, box_size, error_correction, border etc.)
def get_qr(text, **kwargs):
qr = qrcode.QRCode(**kwargs)
qr.add_data(text)
@@ -21,94 +20,12 @@ def get_qr(text, **kwargs):
img = img.get_image()
return img
-
+##################################
+# Converts an image to Base64
+# --------------------------------
+# Parameter:
+# img: Image file
def get_img_b64(img):
stream = BytesIO()
img.save(stream, format='png')
- return str(base64.b64encode(stream.getvalue()), encoding='ascii')
-
-
-def get_qr_text(max_size, text, font='TahomaBold', font_size=0):
- tmpimg = Image.new('P', max_size, 'white')
-
- if font_size == 0:
- text_too_large = True
- font_size = 56
- while text_too_large:
- file_path = resource_stream(__name__, 'fonts/{}.ttf'.format(font))
- try:
- fnt = ImageFont.truetype(file_path, font_size)
- except Exception:
- fnt = ImageFont.load_default()
-
- draw = ImageDraw.Draw(tmpimg)
- left, top, w, h = draw.textbbox((0, 0), text=text, font=fnt)
- if w < max_size[0] - 4 and h < max_size[1] - 4:
- text_too_large = False
- font_size -= 1
- else:
- file_path = resource_stream(__name__, 'fonts/{}.ttf'.format(font))
- try:
- fnt = ImageFont.truetype(file_path, font_size)
- except Exception:
- fnt = ImageFont.load_default()
- draw = ImageDraw.Draw(tmpimg)
- left, top, w, h = draw.textbbox((0, 0), text=text, font=fnt)
-
- img = Image.new('P', (w, h), 'white')
- draw = ImageDraw.Draw(img)
- draw.text((0, 0), text, font=fnt, fill='black')
- return img
-
-
-def get_concat(im1, im2, direction='right'):
- if direction == 'right' or direction == 'left':
- width = im1.width + im2.width
- height = max(im1.height, im2.height)
- elif direction == 'down' or direction == 'up':
- width = max(im1.width, im2.width)
- height = im1.height + im2.height
- else:
- raise ValueError(
- 'Invalid direction "{}" (must be one of "left", "right", "up", or "down")'.format(direction)
- )
-
- dst = Image.new('L', (width, height), 'white')
-
- if direction == 'right' or direction == 'left':
- if im1.height > im2.height:
- im1_y = 0
- im2_y = abs(im1.height-im2.height) // 2
- else:
- im1_y = abs(im1.height-im2.height) // 2
- im2_y = 0
-
- if direction == 'right':
- im1_x = 0
- im2_x = im1.width
- else:
- im1_x = im2.width
- im2_x = 0
- elif direction == 'up' or direction == 'down':
- if im1.width > im2.width:
- im1_x = 0
- im2_x = abs(im1.width-im2.width) // 2
- else:
- im1_x = abs(im1.width-im2.width) // 2
- im2_x = 0
-
- if direction == 'down':
- im1_y = 0
- im2_y = im1.height
- else:
- im1_y = im2.height
- im2_y = 0
- else:
- raise ValueError(
- 'Invalid direction "{}" (must be one of "left", "right", "up", or "down")'.format(direction)
- )
-
- dst.paste(im1, (im1_x, im1_y))
- dst.paste(im2, (im2_x, im2_y))
-
- return dst
+ return str(base64.b64encode(stream.getvalue()), encoding='ascii')
\ No newline at end of file