mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
introduced mesh state table
This commit is contained in:
parent
f3d244e90c
commit
4c556e61fd
9 changed files with 239 additions and 55 deletions
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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"],
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
118
tnc/mesh.py
118
tnc/mesh.py
|
@ -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])
|
||||
|
@ -396,3 +461,16 @@ class MeshRouter():
|
|||
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)
|
13
tnc/modem.py
13
tnc/modem.py
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
19
tnc/sock.py
19
tnc/sock.py
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue