introduced mesh state table

This commit is contained in:
DJ2LS 2023-06-13 14:03:36 +02:00
parent f3d244e90c
commit 4c556e61fd
9 changed files with 239 additions and 55 deletions

View file

@ -72,22 +72,6 @@ if (tbl !== null) {
for (i = 0; i < routes.length; i++) {
/*
var myGrid = document.getElementById("myGrid").value;
try {
var dist = parseInt(distance(myGrid, dxGrid)) + " km";
document.getElementById("dataModalPingDistance").textContent = dist;
} catch {
document.getElementById("dataModalPingDistance").textContent = "---";
}
document.getElementById("dataModalPingDB").textContent =
arg.stations[i]["snr"];
}
*/
var row = document.createElement("tr");
var datetime = new Date(routes[i]["timestamp"] * 1000).toLocaleString(
navigator.language,{
@ -139,6 +123,82 @@ for (i = 0; i < routes.length; i++) {
tbl.appendChild(row);
}
/*-------------------------------------------*/
var routes = arg.mesh_signalling_table;
console.log(routes)
if (typeof routes == "undefined") {
return;
}
var tbl = document.getElementById("mesh-signalling-table");
if (tbl !== null) {
tbl.innerHTML = "";
}
for (i = 0; i < routes.length; i++) {
var row = document.createElement("tr");
var datetime = new Date(routes[i]["timestamp"] * 1000).toLocaleString(
navigator.language,{
hourCycle: 'h23',
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit"
}
);
var timestamp = document.createElement("td");
var timestampText = document.createElement("span");
timestampText.innerText = datetime;
timestamp.appendChild(timestampText);
var destination = document.createElement("td");
var destinationText = document.createElement("span");
destinationText.innerText = routes[i]["destination"];
destination.appendChild(destinationText);
var router = document.createElement("td");
var routerText = document.createElement("span");
routerText.innerText = routes[i]["router"];
router.appendChild(routerText);
var frametype = document.createElement("td");
var frametypeText = document.createElement("span");
frametypeText.innerText = routes[i]["frametype"];
frametype.appendChild(frametypeText);
var payload = document.createElement("td");
var payloadText = document.createElement("span");
payloadText.innerText = routes[i]["payload"];
payload.appendChild(payloadText);
var attempt = document.createElement("td");
var attemptText = document.createElement("span");
attemptText.innerText = routes[i]["attempt"];
attempt.appendChild(attemptText);
var status = document.createElement("td");
var statusText = document.createElement("span");
statusText.innerText = routes[i]["status"];
status.appendChild(statusText);
row.appendChild(timestamp);
row.appendChild(destination);
row.appendChild(router);
row.appendChild(frametype);
row.appendChild(payload);
row.appendChild(attempt);
row.appendChild(status);
tbl.appendChild(row);
}
@ -147,6 +207,6 @@ if (tbl !== null) {
// scroll to bottom of page
// https://stackoverflow.com/a/11715670
window.scrollTo(0, document.body.scrollHeight);
//window.scrollTo(0, document.body.scrollHeight);
}
});

View file

@ -219,6 +219,7 @@ client.on("data", function (socketdata) {
arq_transmission_percent: data["arq_transmission_percent"],
stations: data["stations"],
routing_table: data["routing_table"],
mesh_signalling_table: data["mesh_signalling_table"],
beacon_state: data["beacon_state"],
hamlib_status: data["hamlib_status"],
listen: data["listen"],

View file

@ -49,8 +49,10 @@
</div>
</nav>
<div class="container-fluid mt-5">
<div class="tableFixHead">
<div class="container-fluid h-100 mt-5">
<div class="tableFixHead h-50">
<table class="table table-hover">
<thead>
<tr>
@ -64,17 +66,39 @@
</tr>
</thead>
<tbody id="mesh-table">
<!--
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
-->
<!-- ... -->
</tbody>
</table>
</div>
<div class="tableFixHead h-50">
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Timestamp</th>
<th scope="col">Destination</th>
<th scope="col">Router</th>
<th scope="col">Frametype</th>
<th scope="col">Payload</th>
<th scope="col">Attempt</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody id="mesh-signalling-table">
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>

View file

@ -26,7 +26,7 @@ import structlog
import stats
import ujson as json
from codec2 import FREEDV_MODE, FREEDV_MODE_USED_SLOTS
from queues import DATA_QUEUE_RECEIVED, DATA_QUEUE_TRANSMIT, RX_BUFFER
from queues import DATA_QUEUE_RECEIVED, DATA_QUEUE_TRANSMIT, RX_BUFFER, MESH_RECEIVED_QUEUE
from static import FRAME_TYPE as FR_TYPE
import broadcast

View file

@ -46,9 +46,7 @@ import helpers
import structlog
import ujson as json
from queues import MESH_RECEIVED_QUEUE, MESH_QUEUE_TRANSMIT
MESH_SIGNALLING_TABLE = []
from queues import MESH_RECEIVED_QUEUE, MESH_QUEUE_TRANSMIT, MESH_SIGNALLING_TABLE
class MeshRouter():
def __init__(self):
@ -206,6 +204,9 @@ class MeshRouter():
self.received_routing_table(data_in[:-2])
elif int.from_bytes(data_in[:1], "big") in [FRAME_TYPE.MESH_SIGNALLING_PING.value]:
self.received_mesh_ping(data_in[:-2])
elif int.from_bytes(data_in[:1], "big") in [FRAME_TYPE.MESH_SIGNALLING_PING_ACK.value]:
self.received_mesh_ping_ack(data_in[:-2])
else:
print("wrong mesh data received")
print(data_in)
@ -215,23 +216,24 @@ class MeshRouter():
data = MESH_QUEUE_TRANSMIT.get()
print(data)
if data[0] == "PING":
self.add_mesh_ping_to_signalling_table(data[2])
self.add_mesh_ping_to_signalling_table(helpers.get_crc_24(data[2]).hex(), status="awaiting_ack")
else:
print("wrong mesh command")
def mesh_signalling_dispatcher(self):
# [timestamp, destination, router, frametype, payload, attempt]
# --------------0------------1---------2---------3--------4---------5---- #
# [timestamp, destination, router, frametype, payload, attempt, status]
# --------------0------------1---------2---------3--------4---------5--------6 #
while True:
threading.Event().wait(1.0)
for entry in MESH_SIGNALLING_TABLE:
print(entry)
timestamp = entry[0]
attempt = entry[5]
status = entry[6]
# check for PING cases
if entry[3] == "PING" and attempt < 10:
if entry[3] in ["PING", "PING-ACK"] and attempt < 10 and status not in ["acknowledged"]:
# Calculate the transmission time with exponential increase
@ -242,7 +244,7 @@ class MeshRouter():
entry[5] += 1
print(attempt)
print("transmit mesh ping")
self.transmit_mesh_signalling(entry)
self.transmit_mesh_signalling_ping(entry)
else:
print("wait some more time")
else:
@ -321,25 +323,88 @@ class MeshRouter():
return int((value_old + value) / 2)
def received_mesh_ping(self, data_in):
pass
destination = data_in[1:4].hex()
if destination == Station.mycallsign_crc.hex():
print("its a ping for us")
# use case 1: set status to acknowleding if we are the receiver of a PING
self.add_mesh_ping_to_signalling_table(destination, status="acknowledging")
dxcallsign_crc = Station.mycallsign_crc
self.transmit_mesh_signalling_ping_ack(dxcallsign_crc)
# use case 2: set status to acknowledged if we are out of retries
#self.add_mesh_ping_to_signalling_table(destination, status="acknowledged")
else:
print(f"its a ping for {destination}")
# use case 1: set status to forwarding if we are not hte receiver of a PING
self.add_mesh_ping_to_signalling_table(destination, status="forwarding")
dxcallsign_crc = bytes.fromhex(destination)
self.transmit_mesh_signalling_ping_ack(dxcallsign_crc)
# use case 2: set status to forwarded if we are not the receiver of a PING and out of retries
#self.add_mesh_ping_to_signalling_table(destination, status="forwarded")
def add_mesh_ping_to_signalling_table(self, dxcallsign):
def received_mesh_ping_ack(self, data_in):
# TODO:
# Check if we have a ping callsign already in signalling table
# if PING, then override and make it a PING-ACK
# if not, then add to table
destination = data_in[1:4].hex()
timestamp = time.time()
router = ""
frametype = "PING-ACK"
payload = ""
attempt = 0
status = "forwarding"
new_entry = [timestamp, destination, router, frametype, payload, attempt, status]
print(MESH_SIGNALLING_TABLE)
for _, item in enumerate(MESH_SIGNALLING_TABLE):
# use case 3: PING ACK sets state to processed if we are the initiator of a PING
if destination == Station.mycallsign_crc.hex():
update_entry = [time.time(), destination, "", "PING-ACK", "", 0, "acknowledged"]
print(f"UPDATE AND CHANGE {MESH_SIGNALLING_TABLE[_]} >>> {update_entry}")
MESH_SIGNALLING_TABLE[_] = update_entry
return
# use case 1: PING-ACK updates PING-ACK, but stay at attempts
if destination in item[1] and "PING-ACK" in item[3]:
update_entry = [item[0], destination, "", "PING-ACK", "", item[5], "forwarding"]
print(f"UPDATE {MESH_SIGNALLING_TABLE[_]} >>> {update_entry}")
MESH_SIGNALLING_TABLE[_] = update_entry
return
# use case 2: PING-ACK overwrites PING
# this avoids possible packet loops
if destination in item[1] and "PING" in item[3]:
update_entry = [time.time(), destination, "", "PING-ACK", "", 0, "forwarding"]
print(f"UPDATE AND CHANGE {MESH_SIGNALLING_TABLE[_]} >>> {update_entry}")
MESH_SIGNALLING_TABLE[_] = update_entry
return
if new_entry not in MESH_SIGNALLING_TABLE:
print(f"INSERT {new_entry} >>> SIGNALLING TABLE")
MESH_SIGNALLING_TABLE.append(new_entry)
def add_mesh_ping_to_signalling_table(self, destination, status):
timestamp = time.time()
destination = helpers.get_crc_24(dxcallsign).hex()
router = ""
frametype = "PING"
payload = ""
attempt = 0
# [timestamp, destination, router, frametype, payload, attempt]
# --------------0------------1---------2---------3--------4---------5---- #
new_entry = [timestamp, destination, router, frametype, payload, attempt]
print(MESH_SIGNALLING_TABLE)
# [timestamp, destination, router, frametype, payload, attempt, status]
# --------------0------------1---------2---------3--------4---------5--------6-----#
new_entry = [timestamp, destination, router, frametype, payload, attempt, status]
for _, item in enumerate(MESH_SIGNALLING_TABLE):
# update routing entry if exists
if new_entry[0] in item[0] and new_entry[1] in item[1]:
print(f"UPDATE {MESH_SIGNALLING_TABLE[_]} >>> {new_entry}")
MESH_SIGNALLING_TABLE[_] = new_entry
# update entry if exists
if destination in item[1] and "PING" in item[3]:
update_entry = [item[0], destination, "", "PING", "", item[5], status]
print(f"UPDATE {MESH_SIGNALLING_TABLE[_]} >>> {update_entry}")
MESH_SIGNALLING_TABLE[_] = update_entry
return
# add new routing entry if not exists
if new_entry not in MESH_SIGNALLING_TABLE:
@ -384,7 +449,7 @@ class MeshRouter():
threading.Event().wait(0.01)
def transmit_mesh_signalling(self, data):
def transmit_mesh_signalling_ping(self, data):
dxcallsign_crc = bytes.fromhex(data[1])
frame_type = bytes([FRAME_TYPE.MESH_SIGNALLING_PING.value])
@ -395,4 +460,17 @@ class MeshRouter():
ping_frame[4:7] = helpers.get_crc_24(Station.mycallsign)
ping_frame[7:13] = helpers.callsign_to_bytes(Station.mycallsign)
self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.sig0.value)
def transmit_mesh_signalling_ping_ack(self, dxcallsign_crc):
#dxcallsign_crc = bytes.fromhex(data[1])
frame_type = bytes([FRAME_TYPE.MESH_SIGNALLING_PING_ACK.value])
ping_frame = bytearray(14)
ping_frame[:1] = frame_type
ping_frame[1:4] = dxcallsign_crc
#ping_frame[4:7] = helpers.get_crc_24(Station.mycallsign)
#ping_frame[7:13] = helpers.callsign_to_bytes(Station.mycallsign)
self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.sig0.value)

View file

@ -907,7 +907,9 @@ class RF:
]:
print("dropp")
elif int.from_bytes(bytes(bytes_out[:1]), "big") in [
FRAME_TYPE.MESH_BROADCAST.value
FRAME_TYPE.MESH_BROADCAST.value,
FRAME_TYPE.MESH_SIGNALLING_PING.value,
FRAME_TYPE.MESH_SIGNALLING_PING_ACK.value,
]:
self.log.debug(
"[MDM] [demod_audio] moving data to mesh dispatcher", nbytes=nbytes
@ -1308,10 +1310,11 @@ class RF:
raise ZeroDivisionError
AudioParam.audio_dbfs = 20 * np.log10(rms / 32768)
except Exception as e:
self.log.warning(
"[MDM] fft calculation error - please check your audio setup",
e=e,
)
# FIXME: Disabled for cli cleanup
#self.log.warning(
# "[MDM] fft calculation error - please check your audio setup",
# e=e,
#)
AudioParam.audio_dbfs = -100
rms_counter = 0

View file

@ -15,7 +15,7 @@ MODEM_TRANSMIT_QUEUE = queue.Queue()
# Initialize FIFO queue to store received frames
MESH_RECEIVED_QUEUE = queue.Queue()
MESH_QUEUE_TRANSMIT = queue.Queue()
MESH_COMMAND_STATES = {}
MESH_SIGNALLING_TABLE = []
# Initialize FIFO queue to store audio frames

View file

@ -32,7 +32,7 @@ import structlog
from random import randrange
import ujson as json
from exceptions import NoCallsign
from queues import DATA_QUEUE_TRANSMIT, RX_BUFFER, RIGCTLD_COMMAND_QUEUE, MESH_QUEUE_TRANSMIT
from queues import DATA_QUEUE_TRANSMIT, RX_BUFFER, RIGCTLD_COMMAND_QUEUE, MESH_QUEUE_TRANSMIT, MESH_SIGNALLING_TABLE
SOCKET_QUEUE = queue.Queue()
DAEMON_QUEUE = queue.Queue()
@ -1177,6 +1177,7 @@ def send_tnc_state():
"beacon_state": str(Beacon.beacon_state),
"stations": [],
"routing_table": [],
"mesh_signalling_table" : [],
"mycallsign": str(Station.mycallsign, encoding),
"mygrid": str(Station.mygrid, encoding),
"dxcallsign": str(Station.dxcallsign, encoding),
@ -1215,6 +1216,22 @@ def send_tnc_state():
"timestamp": MeshParam.routing_table[_][5],
}
)
for _, entry in enumerate(MESH_SIGNALLING_TABLE):
output["mesh_signalling_table"].append(
{
"timestamp": MESH_SIGNALLING_TABLE[_][0],
"destination": MESH_SIGNALLING_TABLE[_][1],
"router": MESH_SIGNALLING_TABLE[_][2],
"frametype": MESH_SIGNALLING_TABLE[_][3],
"payload": MESH_SIGNALLING_TABLE[_][4],
"attempt": MESH_SIGNALLING_TABLE[_][5],
"status": MESH_SIGNALLING_TABLE[_][6],
}
)
#print(output)
return json.dumps(output)

View file

@ -163,6 +163,7 @@ class FRAME_TYPE(Enum):
BURST_NACK = 64
MESH_BROADCAST = 100
MESH_SIGNALLING_PING = 101
MESH_SIGNALLING_PING_ACK = 102
CQ = 200
QRV = 201
PING = 210