add more mesh control panels and navigation

This commit is contained in:
Laura Klünder 2023-10-04 23:05:36 +02:00
parent 6c747803b7
commit 7e759fefd5
6 changed files with 80 additions and 19 deletions

View file

@ -0,0 +1,15 @@
{% extends 'control/base.html' %}
{% load i18n %}
{% block heading %}
{{ title }}
{% endblock %}
{% block subcontent %}
<form method="POST" style="max-width:400px;">
{% csrf_token %}
{{ form }}
<button type="submit">{% trans 'Save' %}</button>
</form>
{% endblock %}

View file

@ -6,14 +6,30 @@
{% block subcontent %}
<div class="columns">
<div>
<h4>General</h4>
<p>
<strong>Address:</strong> {{ node.address }}<br>
<strong>Name:</strong> {% if node.name %}{{ node.name }}{% else %}<em>{% trans '(no name)' %}</em>{% endif %}
</p>
<p>
<a class="button" href="{% url "control.mesh_node.edit" pk=node.pk %}">
{% trans 'Edit' %}
</a>
<a class="button" href="{% url "control.mesh_messages" %}?src_nodes={{ node.address }}">
{% trans 'View messages' %}
</a>
</p>
<h4>Firmware</h4>
<strong>Chip:</strong> {{ node.last_messages.CONFIG_FIRMWARE.parsed.get_chip_display }} rev{{ node.last_messages.CONFIG_FIRMWARE.parsed.revision|join:"." }}
<br>
<strong>Firmware:</strong> {{ node.last_messages.CONFIG_FIRMWARE.parsed.project_name }} {{ node.last_messages.CONFIG_FIRMWARE.parsed.version }} (IDF {{ node.last_messages.CONFIG_FIRMWARE.parsed.idf_version }})
<br>
<strong>Compile Date:</strong> {{ node.last_messages.CONFIG_FIRMWARE.parsed.compile_date }} {{ node.last_messages.CONFIG_FIRMWARE.parsed.compile_time }}
<br>
<strong>SHA256:</strong> <small>{{ node.last_messages.CONFIG_FIRMWARE.parsed.app_elf_sha256 }}</small>
<p>
<strong>Chip:</strong> {{ node.last_messages.CONFIG_FIRMWARE.parsed.get_chip_display }} rev{{ node.last_messages.CONFIG_FIRMWARE.parsed.revision|join:"." }}
<br>
<strong>Firmware:</strong> {{ node.last_messages.CONFIG_FIRMWARE.parsed.project_name }} {{ node.last_messages.CONFIG_FIRMWARE.parsed.version }} (IDF {{ node.last_messages.CONFIG_FIRMWARE.parsed.idf_version }})
<br>
<strong>Compile Date:</strong> {{ node.last_messages.CONFIG_FIRMWARE.parsed.compile_date }} {{ node.last_messages.CONFIG_FIRMWARE.parsed.compile_time }}
<br>
<strong>SHA256:</strong> <small>{{ node.last_messages.CONFIG_FIRMWARE.parsed.app_elf_sha256 }}</small>
</p>
</div>
<div>
<h4>Uplink</h4>
@ -32,7 +48,6 @@
</a>
</p>
<h4>Position</h4>
<p>
<strong>X=</strong>{{ node.last_messages.CONFIG_POSITION.parsed.x_pos }}, <strong>Y=</strong>{{ node.last_messages.CONFIG_POSITION.parsed.y_pos }}, <strong>Z=</strong>{{ node.last_messages.CONFIG_POSITION.parsed.z_pos }}

View file

@ -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/<str:pk>/', MeshNodeDetailView.as_view(), name='control.mesh_node.detail'),
path('mesh/<str:pk>/edit/', MeshNodeEditView.as_view(), name='control.mesh_node.edit'),
path('mesh/<str:recipient>/message/<str:msg_type>/', MeshMessageSendView.as_view(), name='control.mesh_message.send'),
path('', ControlPanelIndexView.as_view(), name='control.index'),
]

View file

@ -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"

View file

@ -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"]

View file

@ -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('_', '-')