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.translation import gettext_lazy as _
from c3nav.mapdata.models.geometry.space import RangingBeacon
from c3nav.mesh.dataformats import BoardType, ChipType, FirmwareImage
from c3nav.mesh.messages import ConfigFirmwareMessage, ConfigHardwareMessage
from c3nav.mesh.messages import MeshMessage as MeshMessage
@ -58,12 +59,15 @@ class MeshNodeQuerySet(models.QuerySet):
self._prefetch_firmwares = False
self._prefetch_ota = False
self._prefetch_ota_done = False
self._prefetch_ranging_beacon = False
self._prefetch_ranging_beacon_done = False
def _clone(self):
clone = super()._clone()
clone._prefetch_last_messages = self._prefetch_last_messages
clone._prefetch_firmwares = self._prefetch_firmwares
clone._prefetch_ota = self._prefetch_ota
clone._prefetch_ranging_beacon = self._prefetch_ranging_beacon
return clone
def prefetch_last_messages(self, *types: MeshMessageType):
@ -84,6 +88,11 @@ class MeshNodeQuerySet(models.QuerySet):
clone._prefetch_pta = True
return clone
def prefetch_ranging_beacon(self):
clone = self._chain()
clone._prefetch_ranging_beacon = True
return clone
def _fetch_all(self):
super()._fetch_all()
nodes = None
@ -160,6 +169,20 @@ class MeshNodeQuerySet(models.QuerySet):
except NotSupportedError:
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):
def __init__(self, node):
@ -232,6 +255,14 @@ class MeshNode(models.Model):
except AttributeError:
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
@cached_property
def firmware_description(self) -> FirmwareDescription:

View file

@ -117,6 +117,12 @@
X={{ locator_xyz.0 | cm_to_m }}
Y={{ locator_xyz.1 | 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>
{% else %}
<p>

View file

@ -15,7 +15,15 @@
</tr>
{% for node in nodes %}
<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>
{{ 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>

View file

@ -16,7 +16,7 @@ class NodeListView(MeshControlMixin, ListView):
context_object_name = "nodes"
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()