show ranging beacons in some mesh node views

This commit is contained in:
Laura Klünder 2023-11-25 20:14:07 +01:00
parent 0564828d53
commit 35a8b17b48
4 changed files with 47 additions and 2 deletions

View file

@ -14,6 +14,7 @@ from django.utils import timezone
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from c3nav.mapdata.models.geometry.space import RangingBeacon
from c3nav.mesh.dataformats import BoardType, ChipType, FirmwareImage from c3nav.mesh.dataformats import BoardType, ChipType, FirmwareImage
from c3nav.mesh.messages import ConfigFirmwareMessage, ConfigHardwareMessage from c3nav.mesh.messages import ConfigFirmwareMessage, ConfigHardwareMessage
from c3nav.mesh.messages import MeshMessage as MeshMessage from c3nav.mesh.messages import MeshMessage as MeshMessage
@ -58,12 +59,15 @@ class MeshNodeQuerySet(models.QuerySet):
self._prefetch_firmwares = False self._prefetch_firmwares = False
self._prefetch_ota = False self._prefetch_ota = False
self._prefetch_ota_done = False self._prefetch_ota_done = False
self._prefetch_ranging_beacon = False
self._prefetch_ranging_beacon_done = False
def _clone(self): def _clone(self):
clone = super()._clone() clone = super()._clone()
clone._prefetch_last_messages = self._prefetch_last_messages clone._prefetch_last_messages = self._prefetch_last_messages
clone._prefetch_firmwares = self._prefetch_firmwares clone._prefetch_firmwares = self._prefetch_firmwares
clone._prefetch_ota = self._prefetch_ota clone._prefetch_ota = self._prefetch_ota
clone._prefetch_ranging_beacon = self._prefetch_ranging_beacon
return clone return clone
def prefetch_last_messages(self, *types: MeshMessageType): def prefetch_last_messages(self, *types: MeshMessageType):
@ -84,6 +88,11 @@ class MeshNodeQuerySet(models.QuerySet):
clone._prefetch_pta = True clone._prefetch_pta = True
return clone return clone
def prefetch_ranging_beacon(self):
clone = self._chain()
clone._prefetch_ranging_beacon = True
return clone
def _fetch_all(self): def _fetch_all(self):
super()._fetch_all() super()._fetch_all()
nodes = None nodes = None
@ -160,6 +169,20 @@ class MeshNodeQuerySet(models.QuerySet):
except NotSupportedError: except NotSupportedError:
pass pass
if self._prefetch_ranging_beacon and not self._prefetch_ranging_beacon_done:
if nodes is None:
nodes: dict[str, MeshNode] = {node.pk: node for node in self._result_cache}
try:
for ranging_beacon in RangingBeacon.objects.filter(bssid__in=nodes.keys()).select_related('space'):
# noinspection PyUnresolvedReferences
nodes[ranging_beacon.bssid]._ranging_beacon = ranging_beacon
for node in nodes.values():
if not hasattr(node, "_ranging_beacon"):
node._ranging_beacon = None
self._prefetch_ranging_beacon_done = True
except NotSupportedError:
pass
class LastMessagesByTypeLookup(UserDict): class LastMessagesByTypeLookup(UserDict):
def __init__(self, node): def __init__(self, node):
@ -232,6 +255,14 @@ class MeshNode(models.Model):
except AttributeError: except AttributeError:
return self.ota_updates.order_by('-update__created').first() return self.ota_updates.order_by('-update__created').first()
@cached_property
def ranging_beacon(self) -> Optional["RangingBeacon"]:
try:
# noinspection PyUnresolvedReferences
return self._ranging_beacon
except AttributeError:
return RangingBeacon.objects.filter(bssid=self.address).first()
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
@cached_property @cached_property
def firmware_description(self) -> FirmwareDescription: def firmware_description(self) -> FirmwareDescription:

View file

@ -117,6 +117,12 @@
X={{ locator_xyz.0 | cm_to_m }} X={{ locator_xyz.0 | cm_to_m }}
Y={{ locator_xyz.1 | cm_to_m }} Y={{ locator_xyz.1 | cm_to_m }}
Z={{ locator_xyz.2 | cm_to_m }} Z={{ locator_xyz.2 | cm_to_m }}
{% if node.ranging_beacon %}
<br>
<a href="{% url "editor.ranging_beacons.edit" space=node.ranging_beacon.space_id pk=node.ranging_beacon.pk %}">Ranging Beacon #{{ node.ranging_beacon.pk }}</a>
{% if node.ranging_beacon.comment %}({{ node.ranging_beacon.comment }}){% endif %}
in {{ node.ranging_beacon.space.title }}
{% endif %}
</p> </p>
{% else %} {% else %}
<p> <p>

View file

@ -15,7 +15,15 @@
</tr> </tr>
{% for node in nodes %} {% for node in nodes %}
<tr> <tr>
<td><a href="{% url "mesh.node.detail" pk=node.address %}">{{ node }}</a></td> <td>
<a href="{% url "mesh.node.detail" pk=node.address %}">{{ node }}</a>
{% if node.ranging_beacon %}
<br>
<a href="{% url "editor.ranging_beacons.edit" space=node.ranging_beacon.space_id pk=node.ranging_beacon.pk %}">Ranging Beacon #{{ node.ranging_beacon.pk }}</a>
{% if node.ranging_beacon.comment and node.ranging_beacon.comment != node.name %}({{ node.ranging_beacon.comment }}){% endif %}
in {{ node.ranging_beacon.space.title }}
{% endif %}
</td>
<td> <td>
{{ node.last_messages.CONFIG_BOARD.parsed.board_config.board.pretty_name }}<br> {{ node.last_messages.CONFIG_BOARD.parsed.board_config.board.pretty_name }}<br>
<small>({{ node.last_messages.CONFIG_HARDWARE.parsed.chip.pretty_name }} rev{{ node.last_messages.CONFIG_HARDWARE.parsed.revision_major }}.{{ node.last_messages.CONFIG_HARDWARE.parsed.revision_minor }})</small> <small>({{ node.last_messages.CONFIG_HARDWARE.parsed.chip.pretty_name }} rev{{ node.last_messages.CONFIG_HARDWARE.parsed.revision_major }}.{{ node.last_messages.CONFIG_HARDWARE.parsed.revision_minor }})</small>

View file

@ -16,7 +16,7 @@ class NodeListView(MeshControlMixin, ListView):
context_object_name = "nodes" context_object_name = "nodes"
def get_queryset(self): def get_queryset(self):
return super().get_queryset().prefetch_last_messages().prefetch_firmwares() return super().get_queryset().prefetch_last_messages().prefetch_firmwares().prefetch_ranging_beacon()