mesh route results
This commit is contained in:
parent
c724833542
commit
0343030980
7 changed files with 170 additions and 47 deletions
|
@ -24,10 +24,10 @@ function connect() {
|
|||
window.setTimeout(connect, 500);
|
||||
}
|
||||
ws.onmessage = (event) => {
|
||||
var data = JSON.parse(event.data), line, text;
|
||||
var data = JSON.parse(event.data), line, text, cell, link_tag;
|
||||
switch(data.type) {
|
||||
case 'mesh.log_entry':
|
||||
line = document.createElement("tr"), cell, link_tag;
|
||||
line = document.createElement("tr");
|
||||
|
||||
cell = document.createElement("td");
|
||||
cell.innerText = data.timestamp;
|
||||
|
@ -37,7 +37,7 @@ function connect() {
|
|||
cell.innerText = data.channel;
|
||||
if (data.uplink) {
|
||||
cell.append(document.createElement("br"));
|
||||
link_tag = document.createElement("a")
|
||||
link_tag = document.createElement("a");
|
||||
link_tag.href = "/control/mesh/" + data.uplink;
|
||||
link_tag.innerText = data.uplink;
|
||||
if (node_names[data.uplink]) {
|
||||
|
@ -48,7 +48,7 @@ function connect() {
|
|||
line.appendChild(cell);
|
||||
|
||||
cell = document.createElement("td");
|
||||
link_tag = document.createElement("a")
|
||||
link_tag = document.createElement("a");
|
||||
link_tag.href = "/control/mesh/" + data.node;
|
||||
link_tag.innerText = data.node;
|
||||
if (node_names[data.node]) {
|
||||
|
@ -73,6 +73,54 @@ function connect() {
|
|||
document.getElementById("sending-status-"+data.recipient).appendChild(line);
|
||||
{% endif %}
|
||||
break;
|
||||
|
||||
case 'mesh.msg_received':
|
||||
{% if send_uuid and msg_type == "MESH_ROUTE_REQUEST" %}
|
||||
if (data.msg.route) {
|
||||
link_tag = document.createElement("a");
|
||||
link_tag.href = "/control/mesh/" + data.msg.src;
|
||||
link_tag.innerText = data.msg.src;
|
||||
if (node_names[data.msg.src]) {
|
||||
link_tag.innerText += " ("+node_names[data.msg.src]+")";
|
||||
}
|
||||
if (data.msg.route === "00:00:00:00:00:00") {
|
||||
line = document.createElement("li");
|
||||
line.appendChild(link_tag);
|
||||
document.getElementById("no-routes").appendChild(line);
|
||||
} else {
|
||||
line = document.createElement("tr");
|
||||
|
||||
cell = document.createElement("td");
|
||||
cell.appendChild(link_tag);
|
||||
line.appendChild(cell);
|
||||
|
||||
cell = document.createElement("td");
|
||||
link_tag = document.createElement("a");
|
||||
link_tag.href = "/control/mesh/" + data.msg.route;
|
||||
link_tag.innerText = data.msg.route;
|
||||
if (node_names[data.msg.route]) {
|
||||
link_tag.innerText += " ("+node_names[data.msg.route]+")";
|
||||
}
|
||||
cell.append(link_tag);
|
||||
line.appendChild(cell);
|
||||
|
||||
document.getElementById("route-responses").appendChild(line);
|
||||
}
|
||||
} else {
|
||||
for (var i=0;i<data.msg.trace.length;i++) {
|
||||
line = document.createElement("li");
|
||||
link_tag = document.createElement("a");
|
||||
link_tag.href = "/control/mesh/" + data.msg.trace[i];
|
||||
link_tag.innerText = data.msg.trace[i];
|
||||
if (node_names[data.msg.trace[i]]) {
|
||||
link_tag.innerText += " ("+node_names[data.msg.trace[i]]+")";
|
||||
}
|
||||
line.appendChild(link_tag);
|
||||
document.getElementById("route-trace").appendChild(line);
|
||||
}
|
||||
}
|
||||
{% endif %}
|
||||
break;
|
||||
}
|
||||
|
||||
console.log(data);
|
||||
|
|
|
@ -9,18 +9,45 @@
|
|||
|
||||
{% block subcontent %}
|
||||
<p><a class="button" href="{{ success_url }}">Go back</a></p>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Recipient</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
{% for address, name in recipients %}
|
||||
<tr>
|
||||
<td>{{ address }}{% if name %} ({{ name }}){% endif %}</td>
|
||||
<td id="sending-status-{{ address }}"></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<div class="columns">
|
||||
<div>
|
||||
<h4>Sending progress</h4>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Recipient</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
{% for address, name in recipients %}
|
||||
<tr>
|
||||
<td>{{ address }}{% if name %} ({{ name }}){% endif %}</td>
|
||||
<td id="sending-status-{{ address }}"></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% if msg_type == "MESH_ROUTE_REQUEST" %}
|
||||
<div>
|
||||
<h4>Routes</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans 'Node' %}</th>
|
||||
<th>{% trans 'Route' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="route-responses"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<h4>No Route</h4>
|
||||
<ul id="no-routes"></ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Trace</h4>
|
||||
<ul id="route-trace"></ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include "control/fragment_mesh_websocket.html" %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -14,6 +14,7 @@ from c3nav.control.views.base import ControlPanelMixin
|
|||
from c3nav.mesh.forms import MeshMessageForm, MeshNodeForm
|
||||
from c3nav.mesh.messages import MeshMessageType
|
||||
from c3nav.mesh.models import MeshNode, NodeMessage
|
||||
from c3nav.mesh.utils import get_node_names
|
||||
|
||||
|
||||
class MeshNodeListView(ControlPanelMixin, ListView):
|
||||
|
@ -137,9 +138,7 @@ class MeshMessageSendingView(ControlPanelMixin, TemplateView):
|
|||
data = self.request.session["mesh_msg_%s" % uuid]
|
||||
except KeyError:
|
||||
raise Http404
|
||||
node_names = {
|
||||
node.address: node.name for node in MeshNode.objects.all()
|
||||
}
|
||||
node_names = get_node_names()
|
||||
return {
|
||||
**super().get_context_data(),
|
||||
"node_names": node_names,
|
||||
|
@ -156,7 +155,5 @@ class MeshLogView(ControlPanelMixin, TemplateView):
|
|||
def get_context_data(self, **kwargs):
|
||||
return {
|
||||
**super().get_context_data(),
|
||||
"node_names": {
|
||||
node.address: node.name for node in MeshNode.objects.all()
|
||||
}
|
||||
}
|
||||
"node_names": get_node_names(),
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ from django.utils import timezone
|
|||
|
||||
from c3nav.mesh.utils import get_mesh_comm_group
|
||||
from c3nav.mesh import messages
|
||||
from c3nav.mesh.messages import MeshMessage, BROADCAST_ADDRESS
|
||||
from c3nav.mesh.messages import MeshMessage, MESH_BROADCAST_ADDRESS, MeshMessageType
|
||||
from c3nav.mesh.models import MeshNode, NodeMessage
|
||||
|
||||
|
||||
|
@ -23,7 +23,9 @@ class MeshConsumer(WebsocketConsumer):
|
|||
self.log_text(self.uplink_node, "mesh websocket disconnected")
|
||||
if self.uplink_node is not None:
|
||||
# leave broadcast group
|
||||
async_to_sync(self.channel_layer.group_add)(get_mesh_comm_group(BROADCAST_ADDRESS), self.channel_name)
|
||||
async_to_sync(self.channel_layer.group_discard)(
|
||||
get_mesh_comm_group(MESH_BROADCAST_ADDRESS), self.channel_name
|
||||
)
|
||||
|
||||
# remove all other destinations
|
||||
self.remove_dst_nodes(self.dst_nodes)
|
||||
|
@ -51,7 +53,7 @@ class MeshConsumer(WebsocketConsumer):
|
|||
traceback.print_exc()
|
||||
return
|
||||
|
||||
if msg.dst != messages.ROOT_ADDRESS and msg.dst != messages.PARENT_ADDRESS:
|
||||
if msg.dst != messages.MESH_ROOT_ADDRESS and msg.dst != messages.MESH_PARENT_ADDRESS:
|
||||
print('Received message for forwarding:', msg)
|
||||
# todo: this message isn't for us, forward it
|
||||
return
|
||||
|
@ -67,13 +69,15 @@ class MeshConsumer(WebsocketConsumer):
|
|||
|
||||
# inform signed in uplink node about its layer
|
||||
self.send_msg(messages.MeshLayerAnnounceMessage(
|
||||
src=messages.ROOT_ADDRESS,
|
||||
src=messages.MESH_ROOT_ADDRESS,
|
||||
dst=msg.src,
|
||||
layer=messages.NO_LAYER
|
||||
))
|
||||
|
||||
# add signed in uplink node to broadcast group
|
||||
async_to_sync(self.channel_layer.group_add)('mesh_broadcast', self.channel_name)
|
||||
async_to_sync(self.channel_layer.group_add)(
|
||||
get_mesh_comm_group(MESH_BROADCAST_ADDRESS), self.channel_name
|
||||
)
|
||||
|
||||
# kick out other consumers talking to the same uplink
|
||||
async_to_sync(self.channel_layer.group_send)(get_mesh_comm_group(msg.src), {
|
||||
|
@ -179,7 +183,7 @@ class MeshConsumer(WebsocketConsumer):
|
|||
# tell the node to dump its current information
|
||||
self.send_msg(
|
||||
messages.ConfigDumpMessage(
|
||||
src=messages.ROOT_ADDRESS,
|
||||
src=messages.MESH_ROOT_ADDRESS,
|
||||
dst=address,
|
||||
)
|
||||
)
|
||||
|
@ -230,10 +234,15 @@ class MeshUIConsumer(JsonWebsocketConsumer):
|
|||
if not msg_to_send:
|
||||
return
|
||||
self.scope["session"].save()
|
||||
|
||||
async_to_sync(self.channel_layer.group_add)("mesh_msg_sent", self.channel_name)
|
||||
self.msg_sent_filter = {"sender": self.channel_name}
|
||||
|
||||
if msg_to_send["msg_data"]["msg_id"] == MeshMessageType.MESH_ROUTE_REQUEST:
|
||||
async_to_sync(self.channel_layer.group_add)("mesh_msg_received", self.channel_name)
|
||||
self.msg_received_filter = {"request_id": msg_to_send["msg_data"]["request_id"]}
|
||||
|
||||
for recipient in msg_to_send["recipients"]:
|
||||
print('send to', recipient)
|
||||
MeshMessage.fromjson({
|
||||
'dst': recipient,
|
||||
**msg_to_send["msg_data"],
|
||||
|
@ -243,7 +252,6 @@ class MeshUIConsumer(JsonWebsocketConsumer):
|
|||
self.send_json(data)
|
||||
|
||||
def mesh_msg_sent(self, data):
|
||||
print('got data', data)
|
||||
for key, value in self.msg_sent_filter.items():
|
||||
if isinstance(value, list):
|
||||
if data.get(key, None) not in value:
|
||||
|
@ -253,6 +261,18 @@ class MeshUIConsumer(JsonWebsocketConsumer):
|
|||
return
|
||||
self.send_json(data)
|
||||
|
||||
def mesh_msg_received(self, data):
|
||||
print('got received', data)
|
||||
for key, filter_value in self.msg_received_filter.items():
|
||||
value = data.get(key, data["msg"].get(key, None))
|
||||
if isinstance(filter_value, list):
|
||||
if value not in filter_value:
|
||||
return
|
||||
else:
|
||||
if value != filter_value:
|
||||
return
|
||||
self.send_json(data)
|
||||
|
||||
def disconnect(self, code):
|
||||
async_to_sync(self.channel_layer.group_discard)("mesh_log", self.channel_name)
|
||||
async_to_sync(self.channel_layer.group_discard)("mesh_msg_sent", self.channel_name)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import time
|
||||
from dataclasses import fields as dataclass_fields
|
||||
from functools import cached_property
|
||||
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
|
@ -6,7 +8,7 @@ from django.http import Http404
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from c3nav.mesh.dataformats import LedConfig
|
||||
from c3nav.mesh.messages import MeshMessageType, MeshMessage, ROOT_ADDRESS
|
||||
from c3nav.mesh.messages import MeshMessageType, MeshMessage, MESH_ROOT_ADDRESS, MESH_BROADCAST_ADDRESS
|
||||
from c3nav.mesh.models import MeshNode
|
||||
|
||||
|
||||
|
@ -25,23 +27,26 @@ class MeshMessageForm(forms.Form):
|
|||
super().__init__(*args, initial=initial, **kwargs)
|
||||
|
||||
recipient_root_choices = {
|
||||
'ff:ff:ff:ff:ff:ff': _('broadcast')
|
||||
MESH_BROADCAST_ADDRESS: _('broadcast')
|
||||
}
|
||||
recipient_node_choices = {
|
||||
node_choices = {
|
||||
node.address: str(node) for node in MeshNode.objects.all()
|
||||
}
|
||||
self.recipient_choices = {
|
||||
self.node_choices_flat = {
|
||||
**recipient_root_choices,
|
||||
**recipient_node_choices,
|
||||
**node_choices,
|
||||
}
|
||||
self.node_choices = tuple(node_choices.items())
|
||||
self.node_choices_with_broadcast = (
|
||||
*recipient_root_choices.items(),
|
||||
(_('nodes'), self.node_choices),
|
||||
)
|
||||
|
||||
if self.recipient is None:
|
||||
self.fields['recipients'].choices = (
|
||||
*recipient_root_choices.items(),
|
||||
(_('nodes'), tuple(recipient_node_choices.items()))
|
||||
)
|
||||
self.fields['recipients'].choices = self.node_choices_with_broadcast
|
||||
else:
|
||||
if self.recipient not in self.recipient_choices:
|
||||
raise Http404
|
||||
if self.recipient not in self.node_choices_flat:
|
||||
raise Http404('unknown recipient')
|
||||
self.fields.pop('recipients')
|
||||
|
||||
# noinspection PyMethodOverriding
|
||||
|
@ -56,7 +61,7 @@ class MeshMessageForm(forms.Form):
|
|||
return cls.msg_types[msg_type]
|
||||
|
||||
def get_recipient_display(self):
|
||||
return self.recipient_choices[self.recipient]
|
||||
return self.node_choices_flat[self.recipient]
|
||||
|
||||
def get_cleaned_msg_data(self):
|
||||
msg_data = self.cleaned_data.copy()
|
||||
|
@ -69,7 +74,7 @@ class MeshMessageForm(forms.Form):
|
|||
|
||||
return {
|
||||
'msg_id': self.msg_type,
|
||||
'src': ROOT_ADDRESS,
|
||||
'src': MESH_ROOT_ADDRESS,
|
||||
**self.get_cleaned_msg_data(),
|
||||
}
|
||||
|
||||
|
@ -87,6 +92,22 @@ class MeshMessageForm(forms.Form):
|
|||
}).send()
|
||||
|
||||
|
||||
class MeshRouteRequestForm(MeshMessageForm):
|
||||
msg_type = MeshMessageType.MESH_ROUTE_REQUEST
|
||||
|
||||
address = forms.ChoiceField(choices=())
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["address"].choices = self.node_choices
|
||||
|
||||
def get_msg_data(self):
|
||||
return {
|
||||
**super().get_msg_data(),
|
||||
"request_id": int(time.time()*100000) % 2**32,
|
||||
}
|
||||
|
||||
|
||||
class ConfigUplinkMessageForm(MeshMessageForm):
|
||||
msg_type = MeshMessageType.CONFIG_UPLINK
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ from c3nav.mesh.utils import get_mesh_comm_group, indent_c
|
|||
from c3nav.mesh.dataformats import (BoolFormat, FixedStrFormat, HexFormat, LedConfig, LedConfigFormat,
|
||||
MacAddressesListFormat, MacAddressFormat, SimpleFormat, VarStrFormat)
|
||||
|
||||
ROOT_ADDRESS = '00:00:00:00:00:00'
|
||||
PARENT_ADDRESS = '00:00:00:ff:ff:ff'
|
||||
BROADCAST_ADDRESS = 'ff:ff:ff:ff:ff:ff'
|
||||
MESH_ROOT_ADDRESS = '00:00:00:00:00:00'
|
||||
MESH_PARENT_ADDRESS = '00:00:00:ff:ff:ff'
|
||||
MESH_BROADCAST_ADDRESS = 'ff:ff:ff:ff:ff:ff'
|
||||
NO_LAYER = 0xFF
|
||||
|
||||
@unique
|
||||
|
|
|
@ -4,3 +4,13 @@ def get_mesh_comm_group(address):
|
|||
|
||||
def indent_c(code):
|
||||
return " "+code.replace("\n", "\n ")
|
||||
|
||||
|
||||
def get_node_names():
|
||||
from c3nav.mesh.models import MeshNode
|
||||
return {
|
||||
**{node.address: node.name for node in MeshNode.objects.all()},
|
||||
'ff:ff:ff:ff:ff:ff': "broadcast",
|
||||
'00:00:00:ff:ff:ff': "direct parent",
|
||||
'00:00:00:00:00:00': "root",
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue