diff --git a/src/c3nav/control/templates/control/mesh_firmware_build_detail.html b/src/c3nav/control/templates/control/mesh_firmware_build_detail.html
new file mode 100644
index 00000000..9102464d
--- /dev/null
+++ b/src/c3nav/control/templates/control/mesh_firmware_build_detail.html
@@ -0,0 +1,78 @@
+{% extends 'control/base.html' %}
+{% load i18n mesh_node %}
+
+{% block heading %}{% trans 'Mesh' %}{% endblock %}
+
+{% block subcontent %}
+
{% trans 'Firmware Build' %}
+
+
+
+
+ Project name: {{ build.version.project_name }}
+ Version: {{ build.version.version }}
+ IDF Version: {{ build.version.idf_version }}
+ Uploader: {{ build.version.uploader }}
+ Created: {{ build.version.created }}
+
+
+ Variant: {{ build.variant }}
+ Chip: {{ build.get_chip_display }}
+
+
Compatible boards:
+
+ {% for board in build.boards %}
+ - {{ board.pretty_name }}
+ {% endfor %}
+
+
+
+
Installed nodes
+
+
+ {% trans 'Node' %} |
+ {% trans 'Hardware' %} |
+
+ {% for node in installed_nodes %}
+
+
+ {% mesh_node node %}
+ |
+
+ {{ node.board.pretty_name }} ({{ node.chip.pretty_name }})
+ |
+
+ {% endfor %}
+
+
+
Compatible nodes
+
+
+
+{% endblock %}
diff --git a/src/c3nav/control/templates/control/mesh_firmware_detail.html b/src/c3nav/control/templates/control/mesh_firmware_detail.html
new file mode 100644
index 00000000..4d9ca2c8
--- /dev/null
+++ b/src/c3nav/control/templates/control/mesh_firmware_detail.html
@@ -0,0 +1,103 @@
+{% extends 'control/base.html' %}
+{% load i18n mesh_node %}
+
+{% block heading %}{% trans 'Mesh' %}{% endblock %}
+
+{% block subcontent %}
+ {% trans 'Firmware' %}
+
+
+
+
+ Project name: {{ firmware.project_name }}
+ Version: {{ firmware.version }}
+ IDF Version: {{ firmware.idf_version }}
+ Uploader: {{ firmware.uploader }}
+ Created: {{ firmware.created }}
+
+
+
Builds
+
+
+ {% trans 'Build' %} |
+ {% trans 'Chip' %} |
+ {% trans 'Boards' %} |
+
+ {% for build in builds %}
+
+
+
+ {{ build.variant }}
+
+ |
+ {{ build.get_chip_display }} |
+
+ {% for board in build.boards %}
+ {{ board.pretty_name }}
+ {% endfor %}
+ |
+
+ {% endfor %}
+
+
+
+
+
Installed nodes
+
+
+ {% trans 'Node' %} |
+ {% trans 'Hardware' %} |
+ {% trans 'Build' %} |
+
+ {% for node in installed_nodes %}
+
+
+ {% mesh_node node %}
+ |
+
+ {{ node.board.pretty_name }} ({{ node.chip.pretty_name }})
+ |
+
+ {{ node.firmware_desc.build.variant }}
+ |
+
+ {% endfor %}
+
+
+
Compatible nodes
+
+
+ {% trans 'Node' %} |
+ {% trans 'Hardware' %} |
+ {% trans 'Current Firmware' %} |
+ {% trans 'Compatible Builds' %} |
+
+ {% for node in compatible_nodes %}
+
+
+ {% mesh_node node %}
+ |
+
+ {{ node.board.pretty_name }} ({{ node.chip.pretty_name }})
+ |
+
+ {% if node.firmware_desc.build %}
+
+ {{ node.firmware_desc.project_name }} {{ node.firmware_desc.version }}
+
+ Build {{ node.firmware_desc.build.variant }}
+ {% else %}
+ {{ node.firmware_desc.project_name }} {{ node.firmware_desc.version }}
+ {% endif %}
+ |
+
+ {% for build in node.compatible_builds %}
+ {{ build.variant }}
+ {% endfor %}
+ |
+
+ {% endfor %}
+
+
+
+{% endblock %}
diff --git a/src/c3nav/control/templates/control/mesh_firmwares.html b/src/c3nav/control/templates/control/mesh_firmwares.html
index 731d6f34..6b31fd95 100644
--- a/src/c3nav/control/templates/control/mesh_firmwares.html
+++ b/src/c3nav/control/templates/control/mesh_firmwares.html
@@ -1,7 +1,7 @@
{% extends 'control/base.html' %}
{% load i18n %}
-{% block heading %}{% trans 'Mesh Firmwares' %}{% endblock %}
+{% block heading %}{% trans 'Mesh' %}{% endblock %}
{% block subcontent %}
Firmwares
@@ -23,11 +23,17 @@
{{ firmware.created }} |
{{ firmware.uploader }} |
- {{ firmware.project_name }} {{ firmware.version }} |
+
+
+ {{ firmware.project_name }} {{ firmware.version }}
+
+ |
{{ firmware.idf_version }} |
{% for build in firmware.builds.all %}
- {{ build.variant }} ({{ build.get_chip_display }})
+
+ {{ build.variant }} ({{ build.get_chip_display }})
+
{% endfor %}
|
diff --git a/src/c3nav/control/templates/control/mesh_firmwares_current.html b/src/c3nav/control/templates/control/mesh_firmwares_current.html
index db9be23c..7cff67a7 100644
--- a/src/c3nav/control/templates/control/mesh_firmwares_current.html
+++ b/src/c3nav/control/templates/control/mesh_firmwares_current.html
@@ -1,7 +1,7 @@
{% extends 'control/base.html' %}
{% load i18n mesh_node %}
-{% block heading %}{% trans 'Mesh Firmwares' %}{% endblock %}
+{% block heading %}{% trans 'Mesh' %}{% endblock %}
{% block subcontent %}
Current Firmwares
@@ -22,7 +22,7 @@
{{ firmware.created }} |
{% if firmware.build %}
- {{ firmware.project_name }} {{ firmware.version }}
+ {{ firmware.project_name }} {{ firmware.version }}
{% else %}
{{ firmware.project_name }} {{ firmware.version }}
{{ firmware.sha256_hash }}
@@ -30,7 +30,9 @@
|
{% if firmware.build %}
- {{ firmware.build.variant }} ({{ firmware.chip.pretty_name }})
+
+ {{ firmware.build.variant }} ({{ firmware.chip.pretty_name }})
+
{% else %}
({{ firmware.chip.pretty_name }})
{% endif %}
diff --git a/src/c3nav/control/urls.py b/src/c3nav/control/urls.py
index 9e82a48c..ad0d0925 100644
--- a/src/c3nav/control/urls.py
+++ b/src/c3nav/control/urls.py
@@ -4,9 +4,9 @@ from c3nav.control.views.access import grant_access, grant_access_qr
from c3nav.control.views.announcements import announcement_detail, announcement_list
from c3nav.control.views.base import ControlPanelIndexView
from c3nav.control.views.mapupdates import map_updates
-from c3nav.control.views.mesh import (MeshFirmwaresCurrentListView, MeshFirmwaresListView, MeshLogView,
- MeshMessageListView, MeshMessageSendingView, MeshMessageSendView,
- MeshNodeDetailView, MeshNodeEditView, MeshNodeListView)
+from c3nav.control.views.mesh import (MeshFirmwareBuildDetailView, MeshFirmwareDetailView, MeshFirmwaresCurrentListView,
+ MeshFirmwaresListView, MeshLogView, MeshMessageListView, MeshMessageSendingView,
+ MeshMessageSendView, MeshNodeDetailView, MeshNodeEditView, MeshNodeListView)
from c3nav.control.views.users import UserListView, user_detail
urlpatterns = [
@@ -22,6 +22,9 @@ urlpatterns = [
path('mesh/messages/', MeshMessageListView.as_view(), name='control.mesh.messages'),
path('mesh/firmwares/', MeshFirmwaresListView.as_view(), name='control.mesh.firmwares'),
path('mesh/firmwares/current/', MeshFirmwaresCurrentListView.as_view(), name='control.mesh.firmwares.current'),
+ path('mesh/firmwares//', MeshFirmwareDetailView.as_view(), name='control.mesh.firmwares.detail'),
+ path('mesh/firmwares/builds//', MeshFirmwareBuildDetailView.as_view(),
+ name='control.mesh.firmwares.build.detail'),
path('mesh//', MeshNodeDetailView.as_view(), name='control.mesh.node.detail'),
path('mesh//edit/', MeshNodeEditView.as_view(), name='control.mesh.node.edit'),
path('mesh/message/sending//', MeshMessageSendingView.as_view(), name='control.mesh.sending'),
diff --git a/src/c3nav/control/views/mesh.py b/src/c3nav/control/views/mesh.py
index 44f16605..df940432 100644
--- a/src/c3nav/control/views/mesh.py
+++ b/src/c3nav/control/views/mesh.py
@@ -14,7 +14,7 @@ from c3nav.control.forms import MeshMessageFilterForm
from c3nav.control.views.base import ControlPanelMixin
from c3nav.mesh.forms import MeshMessageForm, MeshNodeForm
from c3nav.mesh.messages import MeshMessage, MeshMessageType
-from c3nav.mesh.models import FirmwareVersion, MeshNode, NodeMessage
+from c3nav.mesh.models import FirmwareBuild, FirmwareVersion, MeshNode, NodeMessage
from c3nav.mesh.utils import get_node_names, group_msg_type_choices
@@ -215,3 +215,76 @@ class MeshFirmwaresCurrentListView(ControlPanelMixin, TemplateView):
**super().get_context_data(),
"firmwares": firmwares,
}
+
+
+class MeshFirmwareDetailView(ControlPanelMixin, DetailView):
+ model = FirmwareVersion
+ template_name = "control/mesh_firmware_detail.html"
+ context_object_name = "firmware"
+
+ def get_queryset(self):
+ return super().get_queryset().prefetch_related('builds', 'builds__firmwarebuildboard_set')
+
+ def get_context_data(self, **kwargs):
+ ctx = super().get_context_data()
+
+ nodes = list(MeshNode.objects.all().prefetch_firmwares().prefetch_last_messages(
+ MeshMessageType.CONFIG_BOARD,
+ ))
+ builds = self.get_object().builds.all()
+
+ build_lookups = set(build.get_firmware_description().get_lookup() for build in builds)
+
+ installed_nodes = []
+ compatible_nodes = []
+ for node in nodes:
+ if node.firmware_desc.get_lookup() in build_lookups:
+ installed_nodes.append(node)
+ else:
+ node.compatible_builds = []
+ for build in builds:
+ if node.board in build.boards:
+ node.compatible_builds.append(build)
+ if node.compatible_builds:
+ compatible_nodes.append(node)
+
+ ctx.update({
+ 'builds': builds,
+ 'installed_nodes': installed_nodes,
+ 'compatible_nodes': compatible_nodes,
+ })
+ return ctx
+
+
+class MeshFirmwareBuildDetailView(ControlPanelMixin, DetailView):
+ model = FirmwareBuild
+ template_name = "control/mesh_firmware_build_detail.html"
+ context_object_name = "build"
+
+ def get_queryset(self):
+ return super().get_queryset().prefetch_related('firmwarebuildboard_set')
+
+ def get_context_data(self, **kwargs):
+ ctx = super().get_context_data()
+
+ nodes = list(MeshNode.objects.all().prefetch_firmwares().prefetch_last_messages(
+ MeshMessageType.CONFIG_BOARD,
+ ))
+
+ build_lookup = self.get_object().get_firmware_description().get_lookup()
+ build_boards = self.get_object().boards
+
+ installed_nodes = []
+ compatible_nodes = []
+ for node in nodes:
+ if node.firmware_desc.get_lookup() == build_lookup:
+ installed_nodes.append(node)
+ else:
+ if node.board in build_boards:
+ compatible_nodes.append(node)
+
+ ctx.update({
+ 'installed_nodes': installed_nodes,
+ 'compatible_nodes': compatible_nodes,
+ })
+ return ctx
diff --git a/src/c3nav/mesh/models.py b/src/c3nav/mesh/models.py
index 1ce84bd5..ac731a9b 100644
--- a/src/c3nav/mesh/models.py
+++ b/src/c3nav/mesh/models.py
@@ -192,6 +192,14 @@ class MeshNode(models.Model):
sha256_hash=firmware_msg.app_desc.app_elf_sha256,
)
+ @cached_property
+ def chip(self) -> ChipType:
+ return self.last_messages[MeshMessageType.CONFIG_HARDWARE].parsed.chip
+
+ @cached_property
+ def board(self) -> ChipType:
+ return self.last_messages[MeshMessageType.CONFIG_BOARD].parsed.board_config.board
+
class MeshUplink(models.Model):
"""
@@ -278,7 +286,7 @@ class FirmwareBuild(models.Model):
@property
def boards(self):
- return [board.board for board in self.firmwarebuildboard_set.all()]
+ return {BoardType[board.board] for board in self.firmwarebuildboard_set.all()}
def serialize(self):
return {
|