Skip to content

Commit 128beb2

Browse files
authored
Merge pull request #109 from netbox-community/LHBL-merge
Merge LHBL Updates for new release
2 parents 74b7125 + 8bc1cfa commit 128beb2

37 files changed

+1757
-263
lines changed

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* @k01ek @cruse1977 @natm
1+
* @k01ek @cruse1977 @cvitan

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
PYTHON_VER?=3.12
2-
NETBOX_VER?=v4.2.1
2+
NETBOX_VER?=v4.3.0
33

44
NAME=netbox-qrcode
55

README.md

Lines changed: 48 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Netbox QR Code Plugin
22

3-
[Netbox](https://github.com/netbox-community/netbox) plugin for generate QR codes for objects: Rack, Device, Cable.
3+
[Netbox](https://github.com/netbox-community/netbox) plugin for generate QR codes for objects: Device, Module, Cable, Powerfeed, Powerpanel, Location
44

55
This plugin depends on [qrcode](https://github.com/lincolnloop/python-qrcode) and [Pillow](https://github.com/python-pillow/Pillow) python library
66

@@ -39,77 +39,63 @@ Restart NetBox and add `netbox-qrcode` to your local_requirements.txt
3939

4040
## Configuration
4141

42-
The following options are available:
42+
### Label Design
4343

44-
* `with_text`: Boolean (default True). Text label will be added to QR code image if enabled.
45-
* `text_template`: [Jinja2](https://jinja.palletsprojects.com/) template with {{ obj }} as context for device, rack, etc., using it ignores `text_fields` and `custom_text`.
44+
Extensive label customisation is possible, it's also possible to include different labels for each object type, for example 2 labels for the Device view.
4645

47-
Example to output name and site in two lines with caption (See also screenshots below):
48-
```
49-
'text_template': 'Name: {{ obj.name }}\nSite: {{ obj.site }}',
50-
```
51-
* `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.
52-
* `font`: String (default TahomaBold) Font name for text label ( Some font include in package, see fonts dir).
53-
* `text_location`: Where to render the text, relative to the QR code. Valid values are `"right"` (default), `"left"`", `"up"`, and `"down"`.
54-
* `custom_text`: String or None (default None) additional text label to QR code image (will be added after text_fields).
55-
* `qr_version`: Integer (default 1) parameter is an integer from 1 to 40 that controls the size of
56-
the QR Code (the smallest, version 1, is a 21x21 matrix).
57-
* `qr_error_correction`: Integer (default 0), controls the error correction used for the
58-
QR Code. The following values are available:
46+
For advice on configuration please see the two links below:
5947

60-
1 - About 7% or less errors can be corrected.
61-
0 - About 15% or less errors can be corrected.
62-
2 - About 30% or less errors can be corrected.
63-
3 - About 25% or less errors can be corrected.
48+
- [General Configuration >>](docs/README_Subpages/README_Configuration.md)
49+
- [Configuration Examples >>](docs/README_Subpages/README_Configuration_ExampleLabelConf.md)
6450

65-
* `qr_box_size`: Integer (default 6), controls how many pixels each "box" of the QR code
66-
is.
67-
* `qr_border`: Integer (default 4), controls how many boxes thick the border should be
68-
(the default is 4, which is the minimum according to the specs).
51+
![Cable QR Code](/docs/img/Configuration_Label_Example_10.png)
6952

70-
### Per object options
7153

72-
Per object options override default options. Per object options dictionary can contains any of default options inside.
54+
### Printing
55+
56+
#### Setting the label printer
57+
58+
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.
59+
60+
![ShowImage](/docs/img/Configuration_Printer_WordPreview.png)
61+
62+
63+
Here is an example of what needs to be considered to print borderless from a Word document. [Go to: Example Zebra ZM400 300dpi label printer and a label 56x32mm. >>](/docs/img/Configuration_Printer_ZM400.png)
64+
65+
66+
#### Setting Browser Print Settings
67+
68+
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.
69+
70+
##### Firefox:
71+
72+
| Parameter | Value |
73+
| --------------------------------------------- | --------------------------- |
74+
| Orientation | Portrait |
75+
| Paper size | User defined |
76+
| Margins | none |
77+
| Scale | Fit to page width or 100% |
78+
| Options --> Print headers and footers | disable |
79+
| Options --> Print backgrounds | disable |
80+
81+
##### Chrome:
82+
Chrome can alter settings between printing and the print preview, therefore the below settings are recomended
83+
84+
| Parameter | Value |
85+
| --------------------------------------------- | --------------------------- |
86+
| Layout | Portrait |
87+
| Paper size | empty !!! |
88+
| Pages per sheet | 1 |
89+
| Margins | none |
90+
| Scale | Default or 100% |
91+
| Options --> PBackground grafics | disable |
92+
93+
![Image](/docs/img/Configuration_Browser_Print_Settings.png)
94+
7395

74-
* `device`: Dict or None (default {'text_fields': ['name', 'serial']}), set None to disble QR code
75-
* `rack`: Dict or None (default {'text_fields': ['name']}) , set None to disble QR code
76-
* `cable`: Dict or None ( defaul {'text_fields': ['_termination_a_device', 'termination_a', '_termination_b_device', 'termination_b',]}), set None to disble QR code
7796

78-
Configuration example:
79-
```
80-
PLUGINS_CONFIG = {
81-
'netbox_qrcode': {
82-
'with_text': True,
83-
'text_fields': ['name', 'serial'],
84-
'font': 'ArialMT',
85-
'font_size': 12, # If the value is 0 or the line does not exist, then the text is automatically adjusted
86-
'custom_text': 'Property of SomeCompany\ntel.8.800333554-CALL',
87-
'text_location': 'up',
88-
'qr_version': 1,
89-
'qr_error_correction': 0,
90-
'qr_box_size': 4,
91-
'qr_border': 4,
92-
# per object options
93-
'cable': None, # disable QR code for Cable object
94-
'rack': {
95-
'text_fields': [
96-
'site',
97-
'name',
98-
'facility_id',
99-
'tenant',
100-
'cf.cf_name'
101-
]
102-
},
103-
'device': {
104-
'qr_box_size': 6,
105-
'custom_text': None,
106-
}
107-
}
108-
}
109-
```
11097

11198
## Contributing
112-
Developing tools for this project based on [ntc-netbox-plugin-onboarding](https://github.com/networktocode/ntc-netbox-plugin-onboarding) repo.
11399

114100
Issues and pull requests are welcomed.
115101

@@ -123,6 +109,3 @@ Rack QR code
123109

124110
Cable QR code
125111
![Cable QR Code](docs/img/qrcode_cable.png)
126-
127-
Device QR code via Jinja2 "text_template" Parameter (Multiline and labeled)
128-
![Cable QR Code](docs/img/qrcode_text_template.png)

develop/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
ARG python_ver=3.12
22
FROM python:${python_ver}
33

4-
ARG netbox_ver=v4.2.1
4+
ARG netbox_ver=main
55
ENV PYTHONUNBUFFERED 1
66

77
RUN mkdir -p /opt
88

99
RUN pip install --upgrade pip
10+
RUN pip install setuptools
11+
1012

1113
# -------------------------------------------------------------------------------------
1214
# Install NetBox

develop/Netbox_Icon.png

2.35 KB
Loading

develop/configuration.py

Lines changed: 219 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,225 @@
157157

158158
# Plugins configuration settings. These settings are used by various plugins that the user may have installed.
159159
# Each key in the dictionary is the name of an installed plugin and its value is a dictionary of settings.
160-
# PLUGINS_CONFIG = {}
160+
PLUGINS_CONFIG = {
161+
162+
'netbox_qrcode': {
163+
164+
## Example Template for Devices
165+
166+
'device_2': {
167+
'title': 'Example 2 (Template for Device)',
168+
'text_template': '<div style="display: inline-block; height: 5mm; width: 15mm"><img src="{{ logo }}" style="width:100%; height:100%; object-fit:fill;""></div><br>{{ obj.name }}<br>Device: {{ obj.id|stringformat:"07d" }}',
169+
'font_size': '4mm',
170+
'label_qr_width': '20mm',
171+
'label_qr_height': '30mm',
172+
'label_qr_text_distance': '2mm',
173+
'label_width': '56mm',
174+
'label_height': '32mm',
175+
'label_edge_top': '0mm',
176+
'label_edge_left': '2mm',
177+
'label_edge_right': '2mm',
178+
'logo': '/media/image-attachments/Netbox_Icon_Example.png',
179+
},
180+
181+
'device_3': {
182+
'title': 'Example 3 (Template for Device)',
183+
'font_size': '4mm',
184+
'label_qr_width': '15mm',
185+
'label_qr_height': '15mm',
186+
'label_qr_text_distance': '2mm',
187+
'label_width': '56mm',
188+
'label_height': '32mm',
189+
'label_edge_top': '0mm',
190+
'label_edge_left': '2mm',
191+
'label_edge_right': '2mm',
192+
'text_location': 'left',
193+
},
194+
195+
'device_4': {
196+
'title': 'Example 4 (Template for Device)',
197+
'font_size': '4mm',
198+
'text_align_horizontal': 'center',
199+
'text_align_vertical': 'middle',
200+
'label_qr_width': '20mm',
201+
'label_qr_height': '20mm',
202+
'label_qr_text_distance': '0mm',
203+
'label_width': '56mm',
204+
'label_height': '32mm',
205+
'label_edge_top': '0mm',
206+
'label_edge_left': '0mm',
207+
'label_edge_right': '0mm',
208+
'with_text': True,
209+
'with_qr': False,
210+
},
211+
212+
'device_5': {
213+
'title': 'Example 5 (Template for Device)',
214+
'font_size': '4mm',
215+
'text_align_horizontal': 'left',
216+
'text_align_vertical': 'middle',
217+
'label_qr_width': '20mm',
218+
'label_qr_height': '20mm',
219+
'label_qr_text_distance': '0mm',
220+
'label_width': '56mm',
221+
'label_height': '32mm',
222+
'label_edge_top': '0mm',
223+
'label_edge_left': '2mm',
224+
'label_edge_right': '0mm',
225+
'with_text': True,
226+
'with_qr': False,
227+
},
228+
229+
'device_6': {
230+
'title': 'Example 6 (Template for Device)',
231+
'font_size': '4mm',
232+
'label_qr_width': '20mm',
233+
'label_qr_height': '20mm',
234+
'label_qr_text_distance': '0mm',
235+
'label_width': '56mm',
236+
'label_height': '32mm',
237+
'label_edge_top': '0mm',
238+
'label_edge_left': '0mm',
239+
'label_edge_right': '0mm',
240+
'with_text': False,
241+
'with_qr': True,
242+
},
243+
244+
'device_7': {
245+
'title': 'Example 7 (Template for Device)',
246+
'font_size': '4mm',
247+
'label_qr_width': '20mm',
248+
'label_qr_height': '20mm',
249+
'label_qr_text_distance': '0mm',
250+
'label_width': '32mm',
251+
'label_height': '56mm',
252+
'label_edge_top': '2mm',
253+
'label_edge_left': '0mm',
254+
'label_edge_right': '0mm',
255+
'text_location': 'up',
256+
'text_align_horizontal': 'center',
257+
'text_align_vertical': 'top',
258+
'label_edge_bottom': '2mm',
259+
},
260+
261+
'device_8': {
262+
'title': 'Example 8 (Template for Device)',
263+
'font_size': '4mm',
264+
'label_qr_width': '20mm',
265+
'label_qr_height': '20mm',
266+
'label_qr_text_distance': '2mm',
267+
'label_width': '32mm',
268+
'label_height': '56mm',
269+
'label_edge_top': '2mm',
270+
'label_edge_left': '0mm',
271+
'label_edge_right': '0mm',
272+
'text_location': 'down',
273+
'text_align_horizontal': 'center',
274+
'text_align_vertical': 'top',
275+
},
276+
277+
'device_9': {
278+
'title': 'Example 9 (Template for Device)',
279+
'font_size': '1mm',
280+
'label_qr_width': '9mm',
281+
'label_qr_height': '9mm',
282+
'label_qr_text_distance': '1mm',
283+
'label_width': '25mm',
284+
'label_height': '10mm',
285+
'label_edge_top': '0.2mm',
286+
'label_edge_left': '0.2mm',
287+
'label_edge_right': '0mm',
288+
},
289+
290+
'device_10': {
291+
'title': 'Example 10 (Template for Device)',
292+
'with_qr': False,
293+
'text_align_horizontal': 'center',
294+
'text_align_vertical': 'middle',
295+
'text_template': '<div style="display: inline-block; height: 8.65mm; width: 30mm"><img src="/media/image-attachments/Netbox_Icon_Example.png" style="width:100%; height:100%; object-fit:fill;"></div><br>'
296+
'{{ obj.name }} <br>'
297+
'<div style="display: inline-block; height: 10mm; width: 10mm"><img src="data:image/png;base64,{{qrCode}}" style="width:100%; height:100%; object-fit:fill;"/></div><br>'
298+
'Device: {{ obj.id|stringformat:"07d" }}'
299+
'<p>&#128541; <font color="red"><b> My label design </b> </font> &#128541;</p>',
300+
301+
'label_width': '56mm',
302+
'label_height': '32mm',
303+
'label_edge_top': '0mm',
304+
'label_edge_left': '0mm',
305+
'label_edge_right': '0mm',
306+
},
307+
308+
309+
## Example Template for Cables
310+
311+
'cable': {
312+
'title': 'Example 1 (Template for Cable)',
313+
'with_qr': False,
314+
'label_edge_left': '0.00mm',
315+
'label_edge_right': '0.00mm',
316+
'label_edge_top': '0.00mm',
317+
'text_align_vertical': 'middle',
318+
'text_align_horizontal': 'center',
319+
'text_template': '<span style="writing-mode: vertical-lr; transform: scale(-1);">'
320+
'{{ obj.label }}</br>'
321+
'{{ obj.label }}</br>'
322+
'{{ obj.label }}</br>'
323+
'{{ obj.label }}</br>'
324+
'{{ obj.label }}</br>'
325+
'{{ obj.label }}</br>'
326+
'{{ obj.label }}</br>'
327+
'{{ obj.label }}</br>'
328+
'{{ obj.label }}</br>'
329+
'{{ obj.label }}</br>'
330+
'{{ obj.label }}</br>'
331+
'{{ obj.label }}</br>'
332+
'{{ obj.label }}</br>'
333+
'</span>'
334+
},
335+
336+
'cable_2': {
337+
'title': 'Example 2 (Template for Cable)',
338+
'with_qr': False,
339+
'label_edge_left': '0.00mm',
340+
'label_edge_right': '0.00mm',
341+
'label_edge_top': '0.00mm',
342+
'text_align_vertical': 'middle',
343+
'text_align_horizontal': 'center',
344+
345+
# QR-Code Image File
346+
'qr_version': 1,
347+
'qr_error_correction': 1,
348+
'qr_box_size': 2,
349+
'qr_border': 0,
350+
351+
'text_template': '<svg id="barcode"></svg>'
352+
'<svg id="barcode"></svg>'
353+
'<svg id="barcode"></svg>'
354+
'<svg id="barcode"></svg>'
355+
''
356+
'<style>'
357+
' #barcode {'
358+
' max-width: 48mm;'
359+
' width: 100%;'
360+
' max-height: 6mm;'
361+
' height: 100%;'
362+
' }'
363+
'</style>'
364+
''
365+
'<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.0/dist/JsBarcode.all.min.js"></script>'
366+
''
367+
'<script>'
368+
' JsBarcode("#barcode", "{{ obj.label }}", {'
369+
' background: "transparent",'
370+
' format: "CODE128",'
371+
' displayValue: true,'
372+
' margin: 0,'
373+
' height: 15'
374+
' });'
375+
'</script>'
376+
}
377+
}
378+
}
161379

162380
# When determining the primary IP address for a device, IPv6 is preferred over IPv4 by default. Set this to True to
163381
# prefer IPv4 instead.

0 commit comments

Comments
 (0)