make it possible to send board config messages
This commit is contained in:
parent
e70bd7e0e2
commit
e75896d44c
4 changed files with 66 additions and 45 deletions
|
@ -145,10 +145,6 @@ class MeshMessageSendView(ControlPanelMixin, FormView):
|
||||||
messages.success(self.request, _('Message sent successfully(?)'))
|
messages.success(self.request, _('Message sent successfully(?)'))
|
||||||
super().form_valid(form)
|
super().form_valid(form)
|
||||||
uuid = uuid4()
|
uuid = uuid4()
|
||||||
from pprint import pprint
|
|
||||||
pprint(form.get_msg_data())
|
|
||||||
pprint(MeshMessage.fromjson(form.get_msg_data()))
|
|
||||||
1/0
|
|
||||||
self.request.session["mesh_msg_%s" % uuid] = {
|
self.request.session["mesh_msg_%s" % uuid] = {
|
||||||
"success_url": self.get_success_url(),
|
"success_url": self.get_success_url(),
|
||||||
"recipients": form.get_recipients(),
|
"recipients": form.get_recipients(),
|
||||||
|
|
|
@ -101,6 +101,12 @@ class EnumFormat(SimpleFormat):
|
||||||
def get_c_parts(self):
|
def get_c_parts(self):
|
||||||
return self.c_struct_name, ""
|
return self.c_struct_name, ""
|
||||||
|
|
||||||
|
def fromjson(self, data):
|
||||||
|
return self.field_type[data]
|
||||||
|
|
||||||
|
def tojson(self, data):
|
||||||
|
return data.name
|
||||||
|
|
||||||
def get_c_definitions(self) -> dict[str, str]:
|
def get_c_definitions(self) -> dict[str, str]:
|
||||||
prefix = normalize_name(self.field_type.__name__).upper()
|
prefix = normalize_name(self.field_type.__name__).upper()
|
||||||
options = []
|
options = []
|
||||||
|
|
|
@ -36,6 +36,11 @@ class LedConfig(StructType, union_type_field="led_type"):
|
||||||
led_type: LedType = field(metadata={"format": EnumFormat(), "c_name": "type"})
|
led_type: LedType = field(metadata={"format": EnumFormat(), "c_name": "type"})
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class NoLedConfig(LedConfig, led_type=LedType.NONE):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class SerialLedConfig(LedConfig, led_type=LedType.SERIAL):
|
class SerialLedConfig(LedConfig, led_type=LedType.SERIAL):
|
||||||
serial_led_type: SerialLedType = field(metadata={"format": EnumFormat(), "c_name": "type"})
|
serial_led_type: SerialLedType = field(metadata={"format": EnumFormat(), "c_name": "type"})
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import time
|
import time
|
||||||
from dataclasses import fields as dataclass_fields
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from c3nav.mesh.dataformats import LedConfig, LedType, SerialLedType, BoardType, BoardConfig
|
from c3nav.mesh.dataformats import BoardConfig, BoardType, LedType, SerialLedType
|
||||||
from c3nav.mesh.messages import MESH_BROADCAST_ADDRESS, MESH_ROOT_ADDRESS, MeshMessage, MeshMessageType
|
from c3nav.mesh.messages import MESH_BROADCAST_ADDRESS, MESH_ROOT_ADDRESS, MeshMessage, MeshMessageType
|
||||||
from c3nav.mesh.models import MeshNode
|
from c3nav.mesh.models import MeshNode
|
||||||
|
|
||||||
|
@ -125,11 +124,11 @@ class ConfigBoardMessageForm(MeshMessageForm):
|
||||||
msg_type = MeshMessageType.CONFIG_BOARD
|
msg_type = MeshMessageType.CONFIG_BOARD
|
||||||
|
|
||||||
# todo: don't use numerical values
|
# todo: don't use numerical values
|
||||||
board = forms.ChoiceField(choices=((item.value, item.name) for item in BoardType),
|
board = forms.ChoiceField(choices=((item.name, item.name) for item in BoardType),
|
||||||
label=_('board'))
|
label=_('board'))
|
||||||
led_type = forms.ChoiceField(choices=((item.value, item.name) for item in LedType),
|
led_type = forms.ChoiceField(choices=((item.name, item.name) for item in LedType),
|
||||||
label=_('LED type'))
|
label=_('LED type'))
|
||||||
led_serial_type = forms.ChoiceField(choices=((item.value or '', item.name) for item in SerialLedType),
|
led_serial_type = forms.ChoiceField(choices=((item.name, item.name) for item in SerialLedType),
|
||||||
label=_('serial LED type'), help_text=_('serial LED only'))
|
label=_('serial LED type'), help_text=_('serial LED only'))
|
||||||
# todo: make this use the modern messages
|
# todo: make this use the modern messages
|
||||||
led_serial_gpio = forms.IntegerField(min_value=0, max_value=48, required=False,
|
led_serial_gpio = forms.IntegerField(min_value=0, max_value=48, required=False,
|
||||||
|
@ -142,15 +141,15 @@ class ConfigBoardMessageForm(MeshMessageForm):
|
||||||
label=_('multpin LED GPIO blue'), help_text=_('multipin LED only'))
|
label=_('multpin LED GPIO blue'), help_text=_('multipin LED only'))
|
||||||
|
|
||||||
uwb_enable = forms.BooleanField(required=False, label=_('UWB enable'))
|
uwb_enable = forms.BooleanField(required=False, label=_('UWB enable'))
|
||||||
uwb_gpio_miso = forms.IntegerField(min_value=-1, max_value=48, required=False,
|
uwb_gpio_miso = forms.IntegerField(min_value=0, max_value=48, required=False,
|
||||||
label=_('UWB GPIO MISO'), help_text=_('UWB only'))
|
label=_('UWB GPIO MISO'), help_text=_('UWB only'))
|
||||||
uwb_gpio_mosi = forms.IntegerField(min_value=-1, max_value=48, required=False,
|
uwb_gpio_mosi = forms.IntegerField(min_value=0, max_value=48, required=False,
|
||||||
label=_('UWB GPIO MOSI'), help_text=_('UWB only'))
|
label=_('UWB GPIO MOSI'), help_text=_('UWB only'))
|
||||||
uwb_gpio_clk = forms.IntegerField(min_value=-1, max_value=48, required=False,
|
uwb_gpio_clk = forms.IntegerField(min_value=0, max_value=48, required=False,
|
||||||
label=_('UWB GPIO CLK'), help_text=_('UWB only'))
|
label=_('UWB GPIO CLK'), help_text=_('UWB only'))
|
||||||
uwb_gpio_cs = forms.IntegerField(min_value=-1, max_value=48, required=False,
|
uwb_gpio_cs = forms.IntegerField(min_value=0, max_value=48, required=False,
|
||||||
label=_('UWB GPIO CS'), help_text=_('UWB only'))
|
label=_('UWB GPIO CS'), help_text=_('UWB only'))
|
||||||
uwb_gpio_irq = forms.IntegerField(min_value=-1, max_value=48, required=False,
|
uwb_gpio_irq = forms.IntegerField(min_value=0, max_value=48, required=False,
|
||||||
label=_('UWB GPIO IRQ'), help_text=_('UWB only'))
|
label=_('UWB GPIO IRQ'), help_text=_('UWB only'))
|
||||||
uwb_gpio_rst = forms.IntegerField(min_value=-1, max_value=48, required=False,
|
uwb_gpio_rst = forms.IntegerField(min_value=-1, max_value=48, required=False,
|
||||||
label=_('UWB GPIO RST'), help_text=_('UWB only'))
|
label=_('UWB GPIO RST'), help_text=_('UWB only'))
|
||||||
|
@ -164,25 +163,25 @@ class ConfigBoardMessageForm(MeshMessageForm):
|
||||||
"prefix": "led_",
|
"prefix": "led_",
|
||||||
"field": "board",
|
"field": "board",
|
||||||
"values": tuple(
|
"values": tuple(
|
||||||
str(cfg.board.value) for cfg in BoardConfig._union_options["board"].values()
|
cfg.board.name for cfg in BoardConfig._union_options["board"].values()
|
||||||
if "led" in cfg.__dataclass_fields__
|
if "led" in cfg.__dataclass_fields__
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"prefix": "led_serial_",
|
"prefix": "led_serial_",
|
||||||
"field": "led_type",
|
"field": "led_type",
|
||||||
"values": (str(LedType.SERIAL.value),),
|
"values": (LedType.SERIAL.name,),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"prefix": "led_multipin_",
|
"prefix": "led_multipin_",
|
||||||
"field": "led_type",
|
"field": "led_type",
|
||||||
"values": (str(LedType.MULTIPIN.value),),
|
"values": (LedType.MULTIPIN.name,),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"prefix": "uwb_",
|
"prefix": "uwb_",
|
||||||
"field": "board",
|
"field": "board",
|
||||||
"values": tuple(
|
"values": tuple(
|
||||||
str(cfg.board.value) for cfg in BoardConfig._union_options["board"].values()
|
cfg.board.name for cfg in BoardConfig._union_options["board"].values()
|
||||||
if "uwb" in cfg.__dataclass_fields__
|
if "uwb" in cfg.__dataclass_fields__
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -196,44 +195,59 @@ class ConfigBoardMessageForm(MeshMessageForm):
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super().clean()
|
cleaned_data = super().clean()
|
||||||
|
|
||||||
led_type = int(cleaned_data["led_type"])
|
board_cfg = BoardConfig._union_options["board"][BoardType[cleaned_data["board"]]]
|
||||||
|
has_led = "led" in board_cfg.__dataclass_fields__
|
||||||
|
has_uwb = "uwb" in board_cfg.__dataclass_fields__
|
||||||
|
|
||||||
if led_type:
|
led_values = {
|
||||||
required_fields = set(field.name for field in dataclass_fields(LedConfig.ledconfig_types[led_type]))
|
"led_type": cleaned_data.pop("led_type"),
|
||||||
else:
|
**{
|
||||||
required_fields = set()
|
name.removeprefix('led_'): cleaned_data.pop(name)
|
||||||
|
for name in tuple(cleaned_data.keys())
|
||||||
errors = {}
|
if name.startswith('led_')
|
||||||
led_config = {
|
}
|
||||||
"led_type": led_type
|
}
|
||||||
|
uwb_values = {
|
||||||
|
name.removeprefix('uwb_'): cleaned_data.pop(name)
|
||||||
|
for name in tuple(cleaned_data.keys())
|
||||||
|
if name.startswith('uwb_')
|
||||||
}
|
}
|
||||||
|
|
||||||
"""for key, value in cleaned_data.items():
|
errors = {}
|
||||||
if key == "recipients":
|
|
||||||
continue
|
|
||||||
if value and key not in required_fields:
|
|
||||||
errors[key] = _("this field is not allowed for this LED type")
|
|
||||||
|
|
||||||
for key in required_fields:
|
if has_led:
|
||||||
value = cleaned_data.pop(key, "")
|
prefix = led_values["led_type"].lower()+'_'
|
||||||
if value == "":
|
cleaned_data["led"] = {
|
||||||
errors[key] = _("this field is required for this LED type")
|
"led_type": led_values["led_type"],
|
||||||
led_config[key] = value"""
|
**{
|
||||||
|
name.removeprefix(prefix): value
|
||||||
|
for name, value in led_values.items()
|
||||||
|
if name.startswith(prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for key, value in tuple(cleaned_data["led"].items()):
|
||||||
|
if value is None:
|
||||||
|
field_name = f'led_{prefix}{key}'
|
||||||
|
if self.fields[field_name].min_value == -1:
|
||||||
|
cleaned_data[key] = -1
|
||||||
|
else:
|
||||||
|
errors[field_name] = _('this field is required')
|
||||||
|
|
||||||
cleaned_data["led_config"] = led_config
|
if has_uwb:
|
||||||
|
cleaned_data["uwb"] = uwb_values
|
||||||
|
for key, value in tuple(cleaned_data["uwb"].items()):
|
||||||
|
if value is None:
|
||||||
|
field_name = f'uwb_{key}'
|
||||||
|
if self.fields[field_name].min_value == -1 or not cleaned_data["uwb"]["enable"]:
|
||||||
|
cleaned_data[key] = -1
|
||||||
|
else:
|
||||||
|
errors[field_name] = _('this field is required')
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
raise ValidationError(errors)
|
raise ValidationError(errors)
|
||||||
|
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
def get_cleaned_msg_data(self):
|
|
||||||
msg_data = super().get_cleaned_msg_data().copy()
|
|
||||||
msg_data = {
|
|
||||||
"led_config": msg_data["led_config"],
|
|
||||||
}
|
|
||||||
return msg_data
|
|
||||||
|
|
||||||
def __init__(self, *args, initial=None, **kwargs):
|
def __init__(self, *args, initial=None, **kwargs):
|
||||||
if initial:
|
if initial:
|
||||||
initial.update(initial.pop('led_config'))
|
initial.update(initial.pop('led_config'))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue