add ranging feature in mesh control
This commit is contained in:
parent
f07b06ec60
commit
5cf839577a
7 changed files with 91 additions and 10 deletions
|
@ -348,19 +348,23 @@ class MeshUIConsumer(AsyncJsonWebsocketConsumer):
|
|||
self.msg_received_filter = {}
|
||||
|
||||
async def connect(self):
|
||||
if not self.scope["user_permisions"].mesh_control:
|
||||
if not self.scope["user_permissions"].mesh_control:
|
||||
raise DenyConnection
|
||||
await self.accept()
|
||||
|
||||
async def receive_json(self, content, **kwargs):
|
||||
if content.get("subscribe", None) == "log":
|
||||
await self.channel_layer.group_add("mesh_log", self.channel_name)
|
||||
if content.get("subscribe", None) == "msg_sent":
|
||||
await self.channel_layer.group_add("mesh_msg_sent", self.channel_name)
|
||||
self.msg_sent_filter = dict(content.get("filter", {}))
|
||||
if content.get("subscribe", None) == "msg_received":
|
||||
await self.channel_layer.group_add("mesh_msg_sent", self.channel_name)
|
||||
self.msg_received_filter = dict(content.get("filter", {}))
|
||||
# disabled because security
|
||||
#if content.get("subscribe", None) == "msg_sent":
|
||||
# await self.channel_layer.group_add("mesh_msg_sent", self.channel_name)
|
||||
# self.msg_sent_filter = dict(content.get("filter", {}))
|
||||
#if content.get("subscribe", None) == "msg_received":
|
||||
# await self.channel_layer.group_add("mesh_msg_sent", self.channel_name)
|
||||
# self.msg_received_filter = dict(content.get("filter", {}))
|
||||
if content.get("subscribe", None) == "ranging":
|
||||
await self.channel_layer.group_add("mesh_msg_received", self.channel_name)
|
||||
self.msg_received_filter = {"msg_type": MeshMessageType.LOCATE_RANGE_RESULTS.name}
|
||||
if "send_msg" in content:
|
||||
msg_to_send = self.scope["session"].pop("mesh_msg_%s" % content["send_msg"], None)
|
||||
if not msg_to_send:
|
||||
|
|
|
@ -265,3 +265,17 @@ class MeshNodeForm(forms.ModelForm):
|
|||
class Meta:
|
||||
model = MeshNode
|
||||
fields = ["name"]
|
||||
|
||||
|
||||
class RangingForm(forms.Form):
|
||||
msg_types = {}
|
||||
|
||||
range_from = forms.MultipleChoiceField(choices=(), required=True)
|
||||
range_to = forms.MultipleChoiceField(choices=(), required=True)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
node_choices = tuple((node.address, str(node)) for node in MeshNode.objects.all())
|
||||
self.fields['range_from'].choices = node_choices
|
||||
self.fields['range_to'].choices = node_choices
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<a href="{% url 'mesh.nodes' %}">Nodes</a> ·
|
||||
<a href="{% url 'mesh.messages' %}">Messages</a> ·
|
||||
<a href="{% url 'mesh.firmwares' %}">Firmwares</a> ·
|
||||
<a href="{% url 'mesh.ranging' %}">Ranging</a> ·
|
||||
<a href="{% url 'mesh.logs' %}">Live logs</a> ·
|
||||
</p>
|
||||
</nav>
|
||||
|
|
|
@ -16,6 +16,8 @@ function connect() {
|
|||
console.log('websocket connected.');
|
||||
{% if send_uuid %}
|
||||
ws.send(JSON.stringify({"send_msg": JSON.parse(document.getElementById('send-uuid').textContent)}));
|
||||
{% elif ranging_form %}
|
||||
ws.send(JSON.stringify({"subscribe": "ranging"}));
|
||||
{% else %}
|
||||
ws.send(JSON.stringify({"subscribe": "log"}));
|
||||
{% endif %}
|
||||
|
@ -90,6 +92,21 @@ function connect() {
|
|||
break;
|
||||
|
||||
case 'mesh.msg_received':
|
||||
{% if ranging_form %}
|
||||
var cell;
|
||||
for (cell of document.querySelectorAll(`[data-range-from="${data.msg.src}"]`)) {
|
||||
cell.innerText = "-";
|
||||
}
|
||||
for (var i=0;i<data.msg.ranges.length;i++) {
|
||||
cell = document.querySelector(
|
||||
`[data-range-from="${data.msg.src}"][data-range-to="${data.msg.ranges[i].peer}"]`
|
||||
);
|
||||
if (cell) cell.innerText = (
|
||||
((data.msg.ranges[i].distance == 0xff) ? "invalid" : `${data.msg.ranges[i].distance}cm`) +
|
||||
` (${data.msg.ranges[i].rssi}dBm)`
|
||||
);
|
||||
}
|
||||
{% endif %}
|
||||
{% if send_uuid and msg_type == "MESH_ROUTE_REQUEST" %}
|
||||
if (data.msg.route) {
|
||||
line = document.createElement('tr');
|
||||
|
|
33
src/c3nav/mesh/templates/mesh/mesh_ranging.html
Normal file
33
src/c3nav/mesh/templates/mesh/mesh_ranging.html
Normal file
|
@ -0,0 +1,33 @@
|
|||
{% extends 'mesh/base.html' %}
|
||||
{% load i18n mesh_node %}
|
||||
|
||||
{% block heading %}{% trans 'Mesh ranging' %}{% endblock %}
|
||||
|
||||
{% block subcontent %}
|
||||
{% if not ranging_form.is_valid %}
|
||||
<form>
|
||||
{{ ranging_form }}
|
||||
<button type="submit">{% trans 'Show ranging' %}</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
{% for range_from in ranging_form.cleaned_data.range_from %}
|
||||
<th>{% mesh_node range_from %}</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
||||
{% for range_to in ranging_form.cleaned_data.range_to %}
|
||||
<tr>
|
||||
<td>{% mesh_node range_to %}</td>
|
||||
{% for range_from in ranging_form.cleaned_data.range_from %}
|
||||
<td data-range-to="{{ range_to }}" data-range-from="{{ range_from }}"></td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% include "mesh/fragment_mesh_websocket.html" %}
|
||||
{% endblock %}
|
|
@ -4,7 +4,7 @@ from c3nav.mesh.consumers import MeshConsumer, MeshUIConsumer
|
|||
from c3nav.mesh.views.firmware import (FirmwareBuildDetailView, FirmwareDetailView, FirmwaresCurrentListView,
|
||||
FirmwaresListView)
|
||||
from c3nav.mesh.views.messages import MeshMessageListView, MeshMessageSendingView, MeshMessageSendView
|
||||
from c3nav.mesh.views.misc import MeshLogView
|
||||
from c3nav.mesh.views.misc import MeshLogView, MeshRangingView
|
||||
from c3nav.mesh.views.nodes import NodeDetailView, NodeEditView, NodeListView
|
||||
|
||||
urlpatterns = [
|
||||
|
@ -15,11 +15,12 @@ urlpatterns = [
|
|||
path('firmwares/current/', FirmwaresCurrentListView.as_view(), name='mesh.firmwares.current'),
|
||||
path('firmwares/<int:pk>/', FirmwareDetailView.as_view(), name='mesh.firmwares.detail'),
|
||||
path('firmwares/builds/<int:pk>/', FirmwareBuildDetailView.as_view(), name='mesh.firmwares.build.detail'),
|
||||
path('<str:pk>/', NodeDetailView.as_view(), name='mesh.node.detail'),
|
||||
path('<str:pk>/edit/', NodeEditView.as_view(), name='mesh.node.edit'),
|
||||
path('nodes/<str:pk>/', NodeDetailView.as_view(), name='mesh.node.detail'),
|
||||
path('nodes/<str:pk>/edit/', NodeEditView.as_view(), name='mesh.node.edit'),
|
||||
path('message/sending/<uuid:uuid>/', MeshMessageSendingView.as_view(), name='mesh.sending'),
|
||||
path('message/<str:recipient>/<str:msg_type>/', MeshMessageSendView.as_view(), name='mesh.send'),
|
||||
path('message/<str:msg_type>/', MeshMessageSendView.as_view(), name='mesh.send'),
|
||||
path('ranging/', MeshRangingView.as_view(), name='mesh.ranging'),
|
||||
]
|
||||
|
||||
websocket_urlpatterns = [
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from django.views.generic import TemplateView
|
||||
|
||||
from c3nav.mesh.forms import RangingForm
|
||||
from c3nav.mesh.utils import get_node_names
|
||||
from c3nav.mesh.views.base import MeshControlMixin
|
||||
|
||||
|
@ -12,3 +13,13 @@ class MeshLogView(MeshControlMixin, TemplateView):
|
|||
**super().get_context_data(),
|
||||
"node_names": get_node_names(),
|
||||
}
|
||||
|
||||
|
||||
class MeshRangingView(TemplateView):
|
||||
template_name = "mesh/mesh_ranging.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
return {
|
||||
"ranging_form": RangingForm(self.request.GET or None),
|
||||
"node_names": get_node_names(),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue