mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-20 19:19:22 -06:00
Store channel frequency & width as independent values
This commit is contained in:
parent
b7317bfe29
commit
075f4907ef
@ -651,10 +651,10 @@ class InterfaceSerializer(PrimaryModelSerializer, LinkTerminationSerializer, Con
|
|||||||
model = Interface
|
model = Interface
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'url', 'display', 'device', 'name', 'label', 'type', 'enabled', 'parent', 'lag', 'mtu', 'mac_address',
|
'id', 'url', 'display', 'device', 'name', 'label', 'type', 'enabled', 'parent', 'lag', 'mtu', 'mac_address',
|
||||||
'wwn', 'mgmt_only', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_width', 'untagged_vlan',
|
'wwn', 'mgmt_only', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency',
|
||||||
'tagged_vlans', 'mark_connected', 'cable', 'link_peer', 'link_peer_type', 'connected_endpoint',
|
'rf_channel_width', 'untagged_vlan', 'tagged_vlans', 'mark_connected', 'cable', 'link_peer',
|
||||||
'connected_endpoint_type', 'connected_endpoint_reachable', 'tags', 'custom_fields', 'created',
|
'link_peer_type', 'connected_endpoint', 'connected_endpoint_type', 'connected_endpoint_reachable', 'tags',
|
||||||
'last_updated', 'count_ipaddresses', '_occupied',
|
'custom_fields', 'created', 'last_updated', 'count_ipaddresses', '_occupied',
|
||||||
]
|
]
|
||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
|
@ -936,7 +936,7 @@ class PowerOutletBulkEditForm(
|
|||||||
class InterfaceBulkEditForm(
|
class InterfaceBulkEditForm(
|
||||||
form_from_model(Interface, [
|
form_from_model(Interface, [
|
||||||
'label', 'type', 'parent', 'lag', 'mac_address', 'wwn', 'mtu', 'mgmt_only', 'mark_connected', 'description',
|
'label', 'type', 'parent', 'lag', 'mac_address', 'wwn', 'mtu', 'mgmt_only', 'mark_connected', 'description',
|
||||||
'mode', 'rf_role', 'rf_channel', 'rf_channel_width',
|
'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width',
|
||||||
]),
|
]),
|
||||||
BootstrapMixin,
|
BootstrapMixin,
|
||||||
AddRemoveTagsForm,
|
AddRemoveTagsForm,
|
||||||
@ -988,7 +988,7 @@ class InterfaceBulkEditForm(
|
|||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = [
|
nullable_fields = [
|
||||||
'label', 'parent', 'lag', 'mac_address', 'wwn', 'mtu', 'description', 'mode', 'rf_channel',
|
'label', 'parent', 'lag', 'mac_address', 'wwn', 'mtu', 'description', 'mode', 'rf_channel',
|
||||||
'rf_channel_width', 'untagged_vlan', 'tagged_vlans',
|
'rf_channel_frequency', 'rf_channel_width', 'untagged_vlan', 'tagged_vlans',
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -595,7 +595,8 @@ class InterfaceCSVForm(CustomFieldModelCSVForm):
|
|||||||
model = Interface
|
model = Interface
|
||||||
fields = (
|
fields = (
|
||||||
'device', 'name', 'label', 'parent', 'lag', 'type', 'enabled', 'mark_connected', 'mac_address', 'wwn',
|
'device', 'name', 'label', 'parent', 'lag', 'type', 'enabled', 'mark_connected', 'mac_address', 'wwn',
|
||||||
'mtu', 'mgmt_only', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_width',
|
'mtu', 'mgmt_only', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency',
|
||||||
|
'rf_channel_width',
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -1014,9 +1014,13 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
|
|||||||
widget=StaticSelectMultiple(),
|
widget=StaticSelectMultiple(),
|
||||||
label='Wireless channel'
|
label='Wireless channel'
|
||||||
)
|
)
|
||||||
|
rf_channel_frequency = forms.IntegerField(
|
||||||
|
required=False,
|
||||||
|
label='Channel frequency (MHz)'
|
||||||
|
)
|
||||||
rf_channel_width = forms.IntegerField(
|
rf_channel_width = forms.IntegerField(
|
||||||
required=False,
|
required=False,
|
||||||
label='Channel width (kHz)'
|
label='Channel width (MHz)'
|
||||||
)
|
)
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
|
@ -1108,8 +1108,8 @@ class InterfaceForm(BootstrapMixin, InterfaceCommonForm, CustomFieldModelForm):
|
|||||||
model = Interface
|
model = Interface
|
||||||
fields = [
|
fields = [
|
||||||
'device', 'name', 'label', 'type', 'enabled', 'parent', 'lag', 'mac_address', 'wwn', 'mtu', 'mgmt_only',
|
'device', 'name', 'label', 'type', 'enabled', 'parent', 'lag', 'mac_address', 'wwn', 'mtu', 'mgmt_only',
|
||||||
'mark_connected', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_width', 'wireless_lans',
|
'mark_connected', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency',
|
||||||
'untagged_vlan', 'tagged_vlans', 'tags',
|
'rf_channel_width', 'wireless_lans', 'untagged_vlan', 'tagged_vlans', 'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device': forms.HiddenInput(),
|
'device': forms.HiddenInput(),
|
||||||
@ -1123,6 +1123,8 @@ class InterfaceForm(BootstrapMixin, InterfaceCommonForm, CustomFieldModelForm):
|
|||||||
}
|
}
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'mode': INTERFACE_MODE_HELP_TEXT,
|
'mode': INTERFACE_MODE_HELP_TEXT,
|
||||||
|
'rf_channel_frequency': "Populated by selected channel (if set)",
|
||||||
|
'rf_channel_width': "Populated by selected channel (if set)",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -480,9 +480,13 @@ class InterfaceCreateForm(ComponentCreateForm, InterfaceCommonForm):
|
|||||||
widget=StaticSelect(),
|
widget=StaticSelect(),
|
||||||
label='Wireless channel'
|
label='Wireless channel'
|
||||||
)
|
)
|
||||||
rf_channel_width = forms.IntegerField(
|
rf_channel_frequency = forms.DecimalField(
|
||||||
required=False,
|
required=False,
|
||||||
label='Channel width'
|
label='Channel frequency (MHz)'
|
||||||
|
)
|
||||||
|
rf_channel_width = forms.DecimalField(
|
||||||
|
required=False,
|
||||||
|
label='Channel width (MHz)'
|
||||||
)
|
)
|
||||||
untagged_vlan = DynamicModelChoiceField(
|
untagged_vlan = DynamicModelChoiceField(
|
||||||
queryset=VLAN.objects.all(),
|
queryset=VLAN.objects.all(),
|
||||||
@ -494,8 +498,8 @@ class InterfaceCreateForm(ComponentCreateForm, InterfaceCommonForm):
|
|||||||
)
|
)
|
||||||
field_order = (
|
field_order = (
|
||||||
'device', 'name_pattern', 'label_pattern', 'type', 'enabled', 'parent', 'lag', 'mtu', 'mac_address',
|
'device', 'name_pattern', 'label_pattern', 'type', 'enabled', 'parent', 'lag', 'mtu', 'mac_address',
|
||||||
'description', 'mgmt_only', 'mark_connected', 'rf_role', 'rf_channel', 'rf_channel_width', 'mode',
|
'description', 'mgmt_only', 'mark_connected', 'rf_role', 'rf_channel', 'rf_channel_frequency',
|
||||||
'untagged_vlan', 'tagged_vlans', 'tags'
|
'rf_channel_width', 'mode', 'untagged_vlan', 'tagged_vlans', 'tags'
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -20,10 +20,15 @@ class Migration(migrations.Migration):
|
|||||||
name='rf_channel',
|
name='rf_channel',
|
||||||
field=models.CharField(blank=True, max_length=50),
|
field=models.CharField(blank=True, max_length=50),
|
||||||
),
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='interface',
|
||||||
|
name='rf_channel_frequency',
|
||||||
|
field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True),
|
||||||
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='interface',
|
model_name='interface',
|
||||||
name='rf_channel_width',
|
name='rf_channel_width',
|
||||||
field=models.PositiveSmallIntegerField(blank=True, null=True),
|
field=models.DecimalField(blank=True, decimal_places=3, max_digits=7, null=True),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='interface',
|
model_name='interface',
|
||||||
|
@ -19,6 +19,7 @@ from utilities.ordering import naturalize_interface
|
|||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
from utilities.query_functions import CollateAsChar
|
from utilities.query_functions import CollateAsChar
|
||||||
from wireless.choices import *
|
from wireless.choices import *
|
||||||
|
from wireless.utils import get_channel_attr
|
||||||
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
@ -537,10 +538,19 @@ class Interface(ComponentModel, BaseInterface, LinkTermination, PathEndpoint):
|
|||||||
blank=True,
|
blank=True,
|
||||||
verbose_name='Wireless channel'
|
verbose_name='Wireless channel'
|
||||||
)
|
)
|
||||||
rf_channel_width = models.PositiveSmallIntegerField(
|
rf_channel_frequency = models.DecimalField(
|
||||||
|
max_digits=7,
|
||||||
|
decimal_places=2,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
verbose_name='Channel width (kHz)'
|
verbose_name='Channel frequency (MHz)'
|
||||||
|
)
|
||||||
|
rf_channel_width = models.DecimalField(
|
||||||
|
max_digits=7,
|
||||||
|
decimal_places=3,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
verbose_name='Channel width (MHz)'
|
||||||
)
|
)
|
||||||
wireless_link = models.ForeignKey(
|
wireless_link = models.ForeignKey(
|
||||||
to='wireless.WirelessLink',
|
to='wireless.WirelessLink',
|
||||||
@ -641,13 +651,33 @@ class Interface(ComponentModel, BaseInterface, LinkTermination, PathEndpoint):
|
|||||||
if self.pk and self.lag_id == self.pk:
|
if self.pk and self.lag_id == self.pk:
|
||||||
raise ValidationError({'lag': "A LAG interface cannot be its own parent."})
|
raise ValidationError({'lag': "A LAG interface cannot be its own parent."})
|
||||||
|
|
||||||
# RF channel attributes may be set only for wireless interfaces
|
# RF role & channel may only be set for wireless interfaces
|
||||||
if self.rf_role and not self.is_wireless:
|
if self.rf_role and not self.is_wireless:
|
||||||
raise ValidationError({'rf_role': "Wireless role may be set only on wireless interfaces."})
|
raise ValidationError({'rf_role': "Wireless role may be set only on wireless interfaces."})
|
||||||
if self.rf_channel and not self.is_wireless:
|
if self.rf_channel and not self.is_wireless:
|
||||||
raise ValidationError({'rf_channel': "Channel may be set only on wireless interfaces."})
|
raise ValidationError({'rf_channel': "Channel may be set only on wireless interfaces."})
|
||||||
if self.rf_channel_width and not self.is_wireless:
|
|
||||||
|
# Validate channel frequency against interface type and selected channel (if any)
|
||||||
|
if self.rf_channel_frequency:
|
||||||
|
if not self.is_wireless:
|
||||||
|
raise ValidationError({
|
||||||
|
'rf_channel_frequency': "Channel frequency may be set only on wireless interfaces.",
|
||||||
|
})
|
||||||
|
if self.rf_channel and self.rf_channel_frequency != get_channel_attr(self.rf_channel, 'frequency'):
|
||||||
|
raise ValidationError({
|
||||||
|
'rf_channel_frequency': "Cannot specify custom frequency with channel selected.",
|
||||||
|
})
|
||||||
|
elif self.rf_channel:
|
||||||
|
self.rf_channel_frequency = get_channel_attr(self.rf_channel, 'frequency')
|
||||||
|
|
||||||
|
# Validate channel width against interface type and selected channel (if any)
|
||||||
|
if self.rf_channel_width:
|
||||||
|
if not self.is_wireless:
|
||||||
raise ValidationError({'rf_channel_width': "Channel width may be set only on wireless interfaces."})
|
raise ValidationError({'rf_channel_width': "Channel width may be set only on wireless interfaces."})
|
||||||
|
if self.rf_channel and self.rf_channel_width != get_channel_attr(self.rf_channel, 'width'):
|
||||||
|
raise ValidationError({'rf_channel_width': "Cannot specify custom width with channel selected."})
|
||||||
|
elif self.rf_channel:
|
||||||
|
self.rf_channel_width = get_channel_attr(self.rf_channel, 'width')
|
||||||
|
|
||||||
# Validate untagged VLAN
|
# Validate untagged VLAN
|
||||||
if self.untagged_vlan and self.untagged_vlan.site not in [self.device.site, None]:
|
if self.untagged_vlan and self.untagged_vlan.site not in [self.device.site, None]:
|
||||||
|
@ -496,8 +496,9 @@ class InterfaceTable(DeviceComponentTable, BaseInterfaceTable, PathEndpointTable
|
|||||||
model = Interface
|
model = Interface
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'name', 'device', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address', 'wwn',
|
'pk', 'name', 'device', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address', 'wwn',
|
||||||
'rf_role', 'rf_channel', 'rf_channel_width', 'description', 'mark_connected', 'cable', 'cable_color',
|
'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'description', 'mark_connected',
|
||||||
'wireless_link', 'link_peer', 'connection', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans',
|
'cable', 'cable_color', 'wireless_link', 'link_peer', 'connection', 'tags', 'ip_addresses', 'untagged_vlan',
|
||||||
|
'tagged_vlans',
|
||||||
)
|
)
|
||||||
default_columns = ('pk', 'name', 'device', 'label', 'enabled', 'type', 'description')
|
default_columns = ('pk', 'name', 'device', 'label', 'enabled', 'type', 'description')
|
||||||
|
|
||||||
|
@ -276,9 +276,25 @@
|
|||||||
<th scope="row">Channel</th>
|
<th scope="row">Channel</th>
|
||||||
<td>{{ object.get_rf_channel_display|placeholder }}</td>
|
<td>{{ object.get_rf_channel_display|placeholder }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Channel Frequency</th>
|
||||||
|
<td>
|
||||||
|
{% if object.rf_channel_frequency %}
|
||||||
|
{{ object.rf_channel_frequency|simplify_decimal }} MHz
|
||||||
|
{% else %}
|
||||||
|
<span class="text-muted">—</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Channel Width</th>
|
<th scope="row">Channel Width</th>
|
||||||
<td>{{ object.rf_channel_width|placeholder }}</td>
|
<td>
|
||||||
|
{% if object.rf_channel_width %}
|
||||||
|
{{ object.rf_channel_width|simplify_decimal }} MHz
|
||||||
|
{% else %}
|
||||||
|
<span class="text-muted">—</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% render_field form.rf_role %}
|
{% render_field form.rf_role %}
|
||||||
{% render_field form.rf_channel %}
|
{% render_field form.rf_channel %}
|
||||||
|
{% render_field form.rf_channel_frequency %}
|
||||||
{% render_field form.rf_channel_width %}
|
{% render_field form.rf_channel_width %}
|
||||||
{% render_field form.wireless_lans %}
|
{% render_field form.wireless_lans %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,4 +31,24 @@
|
|||||||
{{ interface.get_rf_channel_display|placeholder }}
|
{{ interface.get_rf_channel_display|placeholder }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Channel Frequency</th>
|
||||||
|
<td>
|
||||||
|
{% if interface.rf_channel_frequency %}
|
||||||
|
{{ interface.rf_channel_frequency|simplify_decimal }} MHz
|
||||||
|
{% else %}
|
||||||
|
<span class="text-muted">—</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Channel Width</th>
|
||||||
|
<td>
|
||||||
|
{% if interface.rf_channel_width %}
|
||||||
|
{{ interface.rf_channel_width|simplify_decimal }} MHz
|
||||||
|
{% else %}
|
||||||
|
<span class="text-muted">—</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
import decimal
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
@ -146,6 +147,19 @@ def humanize_megabytes(mb):
|
|||||||
return f'{mb} MB'
|
return f'{mb} MB'
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter()
|
||||||
|
def simplify_decimal(value):
|
||||||
|
"""
|
||||||
|
Return the simplest expression of a decimal value. Examples:
|
||||||
|
1.00 => '1'
|
||||||
|
1.20 => '1.2'
|
||||||
|
1.23 => '1.23'
|
||||||
|
"""
|
||||||
|
if type(value) is not decimal.Decimal:
|
||||||
|
return value
|
||||||
|
return str(value).rstrip('0.')
|
||||||
|
|
||||||
|
|
||||||
@register.filter()
|
@register.filter()
|
||||||
def tzoffset(value):
|
def tzoffset(value):
|
||||||
"""
|
"""
|
||||||
|
@ -12,81 +12,79 @@ class WirelessRoleChoices(ChoiceSet):
|
|||||||
|
|
||||||
|
|
||||||
class WirelessChannelChoices(ChoiceSet):
|
class WirelessChannelChoices(ChoiceSet):
|
||||||
CHANNEL_AUTO = 'auto'
|
|
||||||
|
|
||||||
# 2.4 GHz
|
# 2.4 GHz
|
||||||
CHANNEL_24G_1 = '2.4g-1'
|
CHANNEL_24G_1 = '2.4g-1-2412-22'
|
||||||
CHANNEL_24G_2 = '2.4g-2'
|
CHANNEL_24G_2 = '2.4g-2-2417-22'
|
||||||
CHANNEL_24G_3 = '2.4g-3'
|
CHANNEL_24G_3 = '2.4g-3-2422-22'
|
||||||
CHANNEL_24G_4 = '2.4g-4'
|
CHANNEL_24G_4 = '2.4g-4-2427-22'
|
||||||
CHANNEL_24G_5 = '2.4g-5'
|
CHANNEL_24G_5 = '2.4g-5-2432-22'
|
||||||
CHANNEL_24G_6 = '2.4g-6'
|
CHANNEL_24G_6 = '2.4g-6-2437-22'
|
||||||
CHANNEL_24G_7 = '2.4g-7'
|
CHANNEL_24G_7 = '2.4g-7-2442-22'
|
||||||
CHANNEL_24G_8 = '2.4g-8'
|
CHANNEL_24G_8 = '2.4g-8-2447-22'
|
||||||
CHANNEL_24G_9 = '2.4g-9'
|
CHANNEL_24G_9 = '2.4g-9-2452-22'
|
||||||
CHANNEL_24G_10 = '2.4g-10'
|
CHANNEL_24G_10 = '2.4g-10-2457-22'
|
||||||
CHANNEL_24G_11 = '2.4g-11'
|
CHANNEL_24G_11 = '2.4g-11-2462-22'
|
||||||
CHANNEL_24G_12 = '2.4g-12'
|
CHANNEL_24G_12 = '2.4g-12-2467-22'
|
||||||
CHANNEL_24G_13 = '2.4g-13'
|
CHANNEL_24G_13 = '2.4g-13-2472-22'
|
||||||
|
|
||||||
# 5 GHz
|
# 5 GHz
|
||||||
CHANNEL_5G_32 = '5g-32'
|
CHANNEL_5G_32 = '5g-32-5160-20'
|
||||||
CHANNEL_5G_34 = '5g-34'
|
CHANNEL_5G_34 = '5g-34-5170-40'
|
||||||
CHANNEL_5G_36 = '5g-36'
|
CHANNEL_5G_36 = '5g-36-5180-20'
|
||||||
CHANNEL_5G_38 = '5g-38'
|
CHANNEL_5G_38 = '5g-38-5190-40'
|
||||||
CHANNEL_5G_40 = '5g-40'
|
CHANNEL_5G_40 = '5g-40-5200-20'
|
||||||
CHANNEL_5G_42 = '5g-42'
|
CHANNEL_5G_42 = '5g-42-5210-80'
|
||||||
CHANNEL_5G_44 = '5g-44'
|
CHANNEL_5G_44 = '5g-44-5220-20'
|
||||||
CHANNEL_5G_46 = '5g-46'
|
CHANNEL_5G_46 = '5g-46-5230-40'
|
||||||
CHANNEL_5G_48 = '5g-48'
|
CHANNEL_5G_48 = '5g-48-5240-20'
|
||||||
CHANNEL_5G_50 = '5g-50'
|
CHANNEL_5G_50 = '5g-50-5250-160'
|
||||||
CHANNEL_5G_52 = '5g-52'
|
CHANNEL_5G_52 = '5g-52-5260-20'
|
||||||
CHANNEL_5G_54 = '5g-54'
|
CHANNEL_5G_54 = '5g-54-5270-40'
|
||||||
CHANNEL_5G_56 = '5g-56'
|
CHANNEL_5G_56 = '5g-56-5280-20'
|
||||||
CHANNEL_5G_58 = '5g-58'
|
CHANNEL_5G_58 = '5g-58-5290-80'
|
||||||
CHANNEL_5G_60 = '5g-60'
|
CHANNEL_5G_60 = '5g-60-5300-20'
|
||||||
CHANNEL_5G_62 = '5g-62'
|
CHANNEL_5G_62 = '5g-62-5310-40'
|
||||||
CHANNEL_5G_64 = '5g-64'
|
CHANNEL_5G_64 = '5g-64-5320-20'
|
||||||
CHANNEL_5G_100 = '5g-100'
|
CHANNEL_5G_100 = '5g-100-5500-20'
|
||||||
CHANNEL_5G_102 = '5g-102'
|
CHANNEL_5G_102 = '5g-102-5510-40'
|
||||||
CHANNEL_5G_104 = '5g-104'
|
CHANNEL_5G_104 = '5g-104-5520-20'
|
||||||
CHANNEL_5G_106 = '5g-106'
|
CHANNEL_5G_106 = '5g-106-5530-80'
|
||||||
CHANNEL_5G_108 = '5g-108'
|
CHANNEL_5G_108 = '5g-108-5540-20'
|
||||||
CHANNEL_5G_110 = '5g-110'
|
CHANNEL_5G_110 = '5g-110-5550-40'
|
||||||
CHANNEL_5G_112 = '5g-112'
|
CHANNEL_5G_112 = '5g-112-5560-20'
|
||||||
CHANNEL_5G_114 = '5g-114'
|
CHANNEL_5G_114 = '5g-114-5570-160'
|
||||||
CHANNEL_5G_116 = '5g-116'
|
CHANNEL_5G_116 = '5g-116-5580-20'
|
||||||
CHANNEL_5G_118 = '5g-118'
|
CHANNEL_5G_118 = '5g-118-5590-40'
|
||||||
CHANNEL_5G_120 = '5g-120'
|
CHANNEL_5G_120 = '5g-120-5600-20'
|
||||||
CHANNEL_5G_122 = '5g-122'
|
CHANNEL_5G_122 = '5g-122-5610-80'
|
||||||
CHANNEL_5G_124 = '5g-124'
|
CHANNEL_5G_124 = '5g-124-5620-20'
|
||||||
CHANNEL_5G_126 = '5g-126'
|
CHANNEL_5G_126 = '5g-126-5630-40'
|
||||||
CHANNEL_5G_128 = '5g-128'
|
CHANNEL_5G_128 = '5g-128-5640-20'
|
||||||
CHANNEL_5G_132 = '5g-132'
|
CHANNEL_5G_132 = '5g-132-5660-20'
|
||||||
CHANNEL_5G_134 = '5g-134'
|
CHANNEL_5G_134 = '5g-134-5670-40'
|
||||||
CHANNEL_5G_136 = '5g-136'
|
CHANNEL_5G_136 = '5g-136-5680-20'
|
||||||
CHANNEL_5G_138 = '5g-138'
|
CHANNEL_5G_138 = '5g-138-5690-80'
|
||||||
CHANNEL_5G_140 = '5g-140'
|
CHANNEL_5G_140 = '5g-140-5700-20'
|
||||||
CHANNEL_5G_142 = '5g-142'
|
CHANNEL_5G_142 = '5g-142-5710-40'
|
||||||
CHANNEL_5G_144 = '5g-144'
|
CHANNEL_5G_144 = '5g-144-5720-20'
|
||||||
CHANNEL_5G_149 = '5g-149'
|
CHANNEL_5G_149 = '5g-149-5745-20'
|
||||||
CHANNEL_5G_151 = '5g-151'
|
CHANNEL_5G_151 = '5g-151-5755-40'
|
||||||
CHANNEL_5G_153 = '5g-153'
|
CHANNEL_5G_153 = '5g-153-5765-20'
|
||||||
CHANNEL_5G_155 = '5g-155'
|
CHANNEL_5G_155 = '5g-155-5775-80'
|
||||||
CHANNEL_5G_157 = '5g-157'
|
CHANNEL_5G_157 = '5g-157-5785-20'
|
||||||
CHANNEL_5G_159 = '5g-159'
|
CHANNEL_5G_159 = '5g-159-5795-40'
|
||||||
CHANNEL_5G_161 = '5g-161'
|
CHANNEL_5G_161 = '5g-161-5805-20'
|
||||||
CHANNEL_5G_163 = '5g-163'
|
CHANNEL_5G_163 = '5g-163-5815-160'
|
||||||
CHANNEL_5G_165 = '5g-165'
|
CHANNEL_5G_165 = '5g-165-5825-20'
|
||||||
CHANNEL_5G_167 = '5g-167'
|
CHANNEL_5G_167 = '5g-167-5835-40'
|
||||||
CHANNEL_5G_169 = '5g-169'
|
CHANNEL_5G_169 = '5g-169-5845-20'
|
||||||
CHANNEL_5G_171 = '5g-171'
|
CHANNEL_5G_171 = '5g-171-5855-80'
|
||||||
CHANNEL_5G_173 = '5g-173'
|
CHANNEL_5G_173 = '5g-173-5865-20'
|
||||||
CHANNEL_5G_175 = '5g-175'
|
CHANNEL_5G_175 = '5g-175-5875-40'
|
||||||
CHANNEL_5G_177 = '5g-177'
|
CHANNEL_5G_177 = '5g-177-5885-20'
|
||||||
|
|
||||||
CHOICES = (
|
CHOICES = (
|
||||||
(CHANNEL_AUTO, 'Auto'),
|
|
||||||
(
|
(
|
||||||
'2.4 GHz (802.11b/g/n/ax)',
|
'2.4 GHz (802.11b/g/n/ax)',
|
||||||
(
|
(
|
||||||
|
@ -56,7 +56,10 @@ class WirelessLANForm(BootstrapMixin, CustomFieldModelForm):
|
|||||||
class WirelessLinkForm(BootstrapMixin, CustomFieldModelForm):
|
class WirelessLinkForm(BootstrapMixin, CustomFieldModelForm):
|
||||||
device_a = DynamicModelChoiceField(
|
device_a = DynamicModelChoiceField(
|
||||||
queryset=Device.objects.all(),
|
queryset=Device.objects.all(),
|
||||||
label='Device A'
|
label='Device A',
|
||||||
|
initial_params={
|
||||||
|
'interfaces': '$interface_a'
|
||||||
|
}
|
||||||
)
|
)
|
||||||
interface_a = DynamicModelChoiceField(
|
interface_a = DynamicModelChoiceField(
|
||||||
queryset=Interface.objects.all(),
|
queryset=Interface.objects.all(),
|
||||||
@ -69,7 +72,10 @@ class WirelessLinkForm(BootstrapMixin, CustomFieldModelForm):
|
|||||||
)
|
)
|
||||||
device_b = DynamicModelChoiceField(
|
device_b = DynamicModelChoiceField(
|
||||||
queryset=Device.objects.all(),
|
queryset=Device.objects.all(),
|
||||||
label='Device B'
|
label='Device B',
|
||||||
|
initial_params={
|
||||||
|
'interfaces': '$interface_b'
|
||||||
|
}
|
||||||
)
|
)
|
||||||
interface_b = DynamicModelChoiceField(
|
interface_b = DynamicModelChoiceField(
|
||||||
queryset=Interface.objects.all(),
|
queryset=Interface.objects.all(),
|
||||||
|
27
netbox/wireless/utils.py
Normal file
27
netbox/wireless/utils.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from .choices import WirelessChannelChoices
|
||||||
|
|
||||||
|
__all__ = (
|
||||||
|
'get_channel_attr',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_channel_attr(channel, attr):
|
||||||
|
"""
|
||||||
|
Return the specified attribute of a given WirelessChannelChoices value.
|
||||||
|
"""
|
||||||
|
if channel not in WirelessChannelChoices.values():
|
||||||
|
raise ValueError(f"Invalid channel value: {channel}")
|
||||||
|
|
||||||
|
channel_values = channel.split('-')
|
||||||
|
attrs = {
|
||||||
|
'band': channel_values[0],
|
||||||
|
'id': int(channel_values[1]),
|
||||||
|
'frequency': Decimal(channel_values[2]),
|
||||||
|
'width': Decimal(channel_values[3]),
|
||||||
|
}
|
||||||
|
if attr not in attrs:
|
||||||
|
raise ValueError(f"Invalid channel attribute: {attr}")
|
||||||
|
|
||||||
|
return attrs[attr]
|
Loading…
Reference in New Issue
Block a user