diff --git a/src/c3nav/control/templates/control/form.html b/src/c3nav/control/templates/control/form.html new file mode 100644 index 00000000..7eea67e4 --- /dev/null +++ b/src/c3nav/control/templates/control/form.html @@ -0,0 +1,15 @@ +{% extends 'control/base.html' %} +{% load i18n %} + +{% block heading %} + {{ title }} +{% endblock %} + +{% block subcontent %} +
+ {% csrf_token %} + {{ form }} + +
+ +{% endblock %} diff --git a/src/c3nav/control/templates/control/mesh_node_detail.html b/src/c3nav/control/templates/control/mesh_node_detail.html index 7fddf26c..1fd0c080 100644 --- a/src/c3nav/control/templates/control/mesh_node_detail.html +++ b/src/c3nav/control/templates/control/mesh_node_detail.html @@ -6,14 +6,30 @@ {% block subcontent %}
+

General

+

+ Address: {{ node.address }}
+ Name: {% if node.name %}{{ node.name }}{% else %}{% trans '(no name)' %}{% endif %} +

+

+ + {% trans 'Edit' %} + + + {% trans 'View messages' %} + +

+

Firmware

- Chip: {{ node.last_messages.CONFIG_FIRMWARE.parsed.get_chip_display }} rev{{ node.last_messages.CONFIG_FIRMWARE.parsed.revision|join:"." }} -
- Firmware: {{ node.last_messages.CONFIG_FIRMWARE.parsed.project_name }} {{ node.last_messages.CONFIG_FIRMWARE.parsed.version }} (IDF {{ node.last_messages.CONFIG_FIRMWARE.parsed.idf_version }}) -
- Compile Date: {{ node.last_messages.CONFIG_FIRMWARE.parsed.compile_date }} {{ node.last_messages.CONFIG_FIRMWARE.parsed.compile_time }} -
- SHA256: {{ node.last_messages.CONFIG_FIRMWARE.parsed.app_elf_sha256 }} +

+ Chip: {{ node.last_messages.CONFIG_FIRMWARE.parsed.get_chip_display }} rev{{ node.last_messages.CONFIG_FIRMWARE.parsed.revision|join:"." }} +
+ Firmware: {{ node.last_messages.CONFIG_FIRMWARE.parsed.project_name }} {{ node.last_messages.CONFIG_FIRMWARE.parsed.version }} (IDF {{ node.last_messages.CONFIG_FIRMWARE.parsed.idf_version }}) +
+ Compile Date: {{ node.last_messages.CONFIG_FIRMWARE.parsed.compile_date }} {{ node.last_messages.CONFIG_FIRMWARE.parsed.compile_time }} +
+ SHA256: {{ node.last_messages.CONFIG_FIRMWARE.parsed.app_elf_sha256 }} +

Uplink

@@ -32,7 +48,6 @@

-

Position

X={{ node.last_messages.CONFIG_POSITION.parsed.x_pos }}, Y={{ node.last_messages.CONFIG_POSITION.parsed.y_pos }}, Z={{ node.last_messages.CONFIG_POSITION.parsed.z_pos }} diff --git a/src/c3nav/control/urls.py b/src/c3nav/control/urls.py index 626b533f..9c027ff2 100644 --- a/src/c3nav/control/urls.py +++ b/src/c3nav/control/urls.py @@ -1,6 +1,7 @@ from django.urls import path -from c3nav.control.views.mesh import MeshNodeListView, MeshMessageListView, MeshNodeDetailView, MeshMessageSendView +from c3nav.control.views.mesh import MeshNodeListView, MeshMessageListView, MeshNodeDetailView, MeshMessageSendView, \ + MeshNodeEditView from c3nav.control.views.mapupdates import map_updates from c3nav.control.views.announcements import announcement_list, announcement_detail from c3nav.control.views.access import grant_access, grant_access_qr @@ -18,6 +19,7 @@ urlpatterns = [ path('mesh/', MeshNodeListView.as_view(), name='control.mesh_nodes'), path('mesh/messages/', MeshMessageListView.as_view(), name='control.mesh_messages'), path('mesh//', MeshNodeDetailView.as_view(), name='control.mesh_node.detail'), + path('mesh//edit/', MeshNodeEditView.as_view(), name='control.mesh_node.edit'), path('mesh//message//', MeshMessageSendView.as_view(), name='control.mesh_message.send'), path('', ControlPanelIndexView.as_view(), name='control.index'), ] diff --git a/src/c3nav/control/views/mesh.py b/src/c3nav/control/views/mesh.py index 967f55ed..b6da40bf 100644 --- a/src/c3nav/control/views/mesh.py +++ b/src/c3nav/control/views/mesh.py @@ -1,13 +1,14 @@ from django.contrib import messages +from django.contrib.messages.views import SuccessMessageMixin from django.db.models import Max from django.http import Http404 from django.urls import reverse from django.utils.translation import gettext_lazy as _ -from django.views.generic import ListView, DetailView, FormView +from django.views.generic import ListView, DetailView, FormView, UpdateView from c3nav.control.forms import MeshMessageFilterForm from c3nav.control.views.base import ControlPanelMixin -from c3nav.mesh.forms import MeshMessageForm +from c3nav.mesh.forms import MeshMessageForm, MeshNodeForm from c3nav.mesh.messages import MeshMessageType from c3nav.mesh.models import MeshNode, NodeMessage @@ -32,6 +33,22 @@ class MeshNodeDetailView(ControlPanelMixin, DetailView): return super().get_queryset().annotate(last_msg=Max('received_messages__datetime')).prefetch_last_messages() +class MeshNodeEditView(ControlPanelMixin, SuccessMessageMixin, UpdateView): + model = MeshNode + form_class = MeshNodeForm + template_name = "control/form.html" + success_message = _('Name updated successfully') + + def get_context_data(self, **kwargs): + return { + **super().get_context_data(), + 'title': _('Editing mesh node: %s') % self.get_object(), + } + + def get_success_url(self): + return reverse('control.mesh_node.detail', kwargs={'pk': self.get_object().pk}) + + class MeshMessageListView(ControlPanelMixin, ListView): model = NodeMessage template_name = "control/mesh_messages.html" diff --git a/src/c3nav/mesh/forms.py b/src/c3nav/mesh/forms.py index dc62d826..15839462 100644 --- a/src/c3nav/mesh/forms.py +++ b/src/c3nav/mesh/forms.py @@ -166,3 +166,9 @@ class ConfigPositionMessageForm(MeshMessageForm): x_pos = forms.IntegerField(min_value=0, max_value=2**16-1, label=_('X')) y_pos = forms.IntegerField(min_value=0, max_value=2 ** 16 - 1, label=_('Y')) z_pos = forms.IntegerField(min_value=0, max_value=2 ** 16 - 1, label=_('Z')) + + +class MeshNodeForm(forms.ModelForm): + class Meta: + model = MeshNode + fields = ["name"] \ No newline at end of file diff --git a/src/c3nav/mesh/messages.py b/src/c3nav/mesh/messages.py index 24b7f597..401d1478 100644 --- a/src/c3nav/mesh/messages.py +++ b/src/c3nav/mesh/messages.py @@ -90,11 +90,17 @@ class MeshMessage: def fromjson(cls, data) -> M: kwargs = data.copy() klass = cls.msg_types[kwargs.pop('msg_id')] + kwargs = klass.upgrade_json(kwargs) + names = set(field.name for field in fields(klass)) for field_ in fields(klass): if is_dataclass(field_.type): kwargs[field_.name] = field_.type.fromjson(kwargs[field_.name]) return klass(**kwargs) + @classmethod + def upgrade_json(cls, data): + return data + def send(self): async_to_sync(channels.layers.get_channel_layer().group_send)(get_mesh_comm_group(self.dst), { "type": "mesh.send", @@ -256,14 +262,14 @@ class ConfigFirmwareMessage(MeshMessage, msg_id=MeshMessageType.CONFIG_FIRMWARE) app_elf_sha256: str = field(metadata={"format": HexFormat(32)}) reserv2: list[int] = field(metadata={"format": SimpleFormat('20I')}, repr=False) - def to_model_data(self): - return { - 'chip': self.chip, - 'project_name': self.project_name, - 'version': self.version, - 'idf_version': self.idf_version, - 'sha256_hash': self.app_elf_sha256, - } + @classmethod + def upgrade_json(cls, data): + data = data.copy() # todo: deepcopy? + print(data) + if 'revision' in data: + data['revision_major'], data['revision_minor'] = data.pop('revision') + print(data) + return data def get_chip_display(self): return ChipType(self.chip).name.replace('_', '-')