diff --git a/gui/daemon.js b/gui/daemon.js
index 23d04534..77c2cec4 100644
--- a/gui/daemon.js
+++ b/gui/daemon.js
@@ -227,7 +227,8 @@ exports.startTNC = function (
auto_tune,
tx_delay,
tci_ip,
- tci_port
+ tci_port,
+ enable_mesh
) {
var json_command = JSON.stringify({
type: "set",
@@ -264,6 +265,7 @@ exports.startTNC = function (
tx_delay: tx_delay,
tci_ip: tci_ip,
tci_port: tci_port,
+ enable_mesh: enable_mesh
},
],
});
diff --git a/gui/main.js b/gui/main.js
index 28b86514..03ea87fd 100644
--- a/gui/main.js
+++ b/gui/main.js
@@ -101,7 +101,8 @@ const configDefaultSettings =
"enable_auto_retry" : "False", \
"tx_delay" : 0, \
"auto_start": 0, \
- "enable_sys_notification": 1 \
+ "enable_sys_notification": 1, \
+ "enable_mesh_features": "False" \
}';
if (!fs.existsSync(configPath)) {
@@ -127,7 +128,6 @@ for (key in parsedConfig) {
}
}
sysInfo.info("------------------------------------------ ");
-
/*
var chatDB = path.join(configFolder, 'chatDB.json')
// create chat database file if not exists
@@ -166,6 +166,7 @@ fs.mkdir(receivedFilesFolder, {
let win = null;
let data = null;
let logViewer = null;
+let meshViewer = null;
var daemonProcess = null;
// create a splash screen
@@ -249,6 +250,29 @@ function createWindow() {
}
});
+ meshViewer = new BrowserWindow({
+ height: 900,
+ width: 600,
+ show: false,
+ //parent: win,
+ webPreferences: {
+ preload: require.resolve("./preload-mesh.js"),
+ nodeIntegration: true,
+ },
+ });
+
+ meshViewer.loadFile("src/mesh-module.html");
+ meshViewer.setMenuBarVisibility(false);
+
+ // Emitted when the window is closed.
+ meshViewer.on("close", function (evt) {
+ if (meshViewer !== null) {
+ evt.preventDefault();
+ meshViewer.hide();
+ } else {
+ this.close();
+ }
+ });
// Emitted when the window is closed.
win.on("closed", function () {
console.log("closing all windows.....");
@@ -392,6 +416,11 @@ ipcMain.on("request-clear-chat-connected", () => {
chat.webContents.send("action-clear-reception-status");
});
+ipcMain.on("request-update-dbclean-spinner", () => {
+ //Turn off dbclean spinner
+ win.webContents.send("action-update-dbclean-spinner");
+});
+
// UPDATE TNC CONNECTION
ipcMain.on("request-update-tnc-ip", (event, data) => {
win.webContents.send("action-update-tnc-ip", data);
@@ -404,6 +433,7 @@ ipcMain.on("request-update-daemon-ip", (event, data) => {
ipcMain.on("request-update-tnc-state", (event, arg) => {
win.webContents.send("action-update-tnc-state", arg);
+ meshViewer.send("action-update-mesh-table", arg)
//data.webContents.send('action-update-tnc-state', arg);
});
@@ -483,6 +513,11 @@ ipcMain.on("request-open-tnc-log", () => {
logViewer.show();
});
+ipcMain.on("request-open-mesh-module", () => {
+ meshViewer.show();
+});
+
+
//file selector
ipcMain.on("get-file-path", (event, data) => {
dialog
@@ -901,6 +936,7 @@ function close_all() {
win.destroy();
chat.destroy();
logViewer.destroy();
+ meshViewer.destroy();
app.quit();
}
diff --git a/gui/preload-chat.js b/gui/preload-chat.js
index f437f5cd..bb0170a4 100644
--- a/gui/preload-chat.js
+++ b/gui/preload-chat.js
@@ -683,7 +683,9 @@ ipcRenderer.on("action-update-transmission-status", (event, arg) => {
document.getElementById("txtConnectedWithChat").textContent = data.dxcallsign;
- console.log(data.status);
+if (typeof data.uuid === undefined) return;
+
+ //console.log(data.status);
if (data.uuid !== "no-uuid") {
db.get(data.uuid, {
attachments: true,
@@ -1054,16 +1056,16 @@ update_chat = function (obj) {
}
// check if wrong status message
- if (obj.status == "transmit" && obj.percent == 0) {
+ if (obj.status == "transmit" && obj.type == "transmit" && obj.percent < 100) {
var TimeDifference = new Date().getTime() / 1000 - obj.timestamp;
- if (TimeDifference > 3600) {
- db.upsert(obj._id, function (doc) {
- if (!doc.status) {
- doc.status = "failed";
- }
- return doc;
- });
- obj.status = "failed";
+ if (TimeDifference > 21600) { //Six hours
+ console.log("Resetting message to failed state since in transmit status for over 6 hours:")
+ console.log(obj);
+ db.upsert(obj._id, function (doc) {
+ doc.status = "failed";
+ return doc;
+ });
+ obj.status = "failed";
}
}
if (typeof obj.new == "undefined") {
@@ -1440,12 +1442,14 @@ update_chat = function (obj) {
if (obj.status == "failed") {
var progressbar_bg = "bg-danger";
var percent_value = "TRANSMISSION FAILED";
+ //Set to 100 so progressbar background populates
+ obj.percent=100;
} else if (obj.status == "transmitted") {
var progressbar_bg = "bg-success";
var percent_value = "TRANSMITTED";
} else {
var progressbar_bg = "bg-primary";
- var percent_value = obj.percent;
+ var percent_value = obj.percent + " %";
}
//Sneak in low graphics mode if so enabled for progress bars
@@ -1487,9 +1491,9 @@ update_chat = function (obj) {
}%;" aria-valuenow="${
obj.percent
}" aria-valuemin="0" aria-valuemax="100">
-
${percent_value} % - ${obj.bytesperminute} Bpm
+ }-progress-information">${percent_value} - ${obj.bytesperminute} Bpm
@@ -1510,8 +1514,8 @@ update_chat = function (obj) {
// console.log(obj.attempt)
if (
- !obj.status == "broadcast_transmit" ||
- !obj.status == "broadcast_received"
+ obj.status != "broadcast_transmit" ||
+ obj.status != "broadcast_received"
) {
document.getElementById("msg-" + obj._id + "-status").innerHTML =
get_icon_for_state(obj.status);
@@ -1577,8 +1581,8 @@ update_chat = function (obj) {
"msg-" + obj._id + "-progress-information"
).innerHTML = "TRANSMITTED - " + obj.bytesperminute + " Bpm";
} else if (
- !obj.status == "broadcast_transmit" ||
- !obj.status == "broadcast_received"
+ obj.status != "broadcast_transmit" ||
+ obj.status != "broadcast_received"
) {
document
.getElementById("msg-" + obj._id + "-progress")
@@ -2909,4 +2913,5 @@ async function dbClean() {
itemCount +
" items removed from database. It's recommended you now restart the GUI."
);
+ ipcRenderer.send("request-update-dbclean-spinner");
}
diff --git a/gui/preload-main.js b/gui/preload-main.js
index caa8cf2b..bcf99f48 100644
--- a/gui/preload-main.js
+++ b/gui/preload-main.js
@@ -28,6 +28,7 @@ var appDataFolder =
var configFolder = path.join(appDataFolder, "FreeDATA");
var configPath = path.join(configFolder, "config.json");
var config = require(configPath);
+
const contrib = [
"DK5SM",
"DL4IAZ",
@@ -343,9 +344,9 @@ window.addEventListener("DOMContentLoaded", () => {
}
if (config.low_bandwidth_mode == "True") {
- document.getElementById("500HzModeSwitch").checked = true;
+ document.getElementById("250HzModeSwitch").checked = true;
} else {
- document.getElementById("500HzModeSwitch").checked = false;
+ document.getElementById("250HzModeSwitch").checked = false;
}
if (config.high_graphics == "True") {
@@ -396,6 +397,21 @@ window.addEventListener("DOMContentLoaded", () => {
document.getElementById("NotificationSwitch").checked = false;
}
+ if(config.enable_mesh_features.toLowerCase() == "true"){
+ document.getElementById("liMeshTable").style.visibility = "visible";
+ document.getElementById("liMeshTable").style.display = "block";
+ document.getElementById("enableMeshSwitch").checked = true;
+
+
+ } else {
+ document.getElementById("liMeshTable").style.visibility = "hidden";
+ document.getElementById("liMeshTable").style.display = "none";
+ document.getElementById("enableMeshSwitch").checked = false;
+
+ }
+
+
+
// theme selector
changeGuiDesign(config.theme);
@@ -1142,8 +1158,8 @@ window.addEventListener("DOMContentLoaded", () => {
});
// enable 500z Switch clicked
- document.getElementById("500HzModeSwitch").addEventListener("click", () => {
- if (document.getElementById("500HzModeSwitch").checked == true) {
+ document.getElementById("250HzModeSwitch").addEventListener("click", () => {
+ if (document.getElementById("250HzModeSwitch").checked == true) {
config.low_bandwidth_mode = "True";
} else {
config.low_bandwidth_mode = "False";
@@ -1243,6 +1259,22 @@ window.addEventListener("DOMContentLoaded", () => {
FD.saveConfig(config, configPath);
});
+ // enable MESH Switch clicked
+ document.getElementById("enableMeshSwitch").addEventListener("click", () => {
+ if (document.getElementById("enableMeshSwitch").checked == true) {
+ config.enable_mesh_features = "True";
+ document.getElementById("liMeshTable").style.visibility = "visible";
+ document.getElementById("liMeshTable").style.display = "block";
+ } else {
+ config.enable_mesh_features = "False";
+ document.getElementById("liMeshTable").style.visibility = "hidden";
+ document.getElementById("liMeshTable").style.display = "none";
+ }
+ //fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
+ FD.saveConfig(config, configPath);
+ });
+
+
// enable is writing switch clicked
document.getElementById("enable_is_writing").addEventListener("click", () => {
if (document.getElementById("enable_is_writing").checked == true) {
@@ -1430,6 +1462,16 @@ window.addEventListener("DOMContentLoaded", () => {
var handshake = document.getElementById("hamlib_handshake").value;
var tx_delay = document.getElementById("tx_delay").value;
+ if (document.getElementById("enableMeshSwitch").checked == true) {
+ var enable_mesh_features = "True";
+ document.getElementById("liMeshTable").style.visibility = "visible";
+ document.getElementById("liMeshTable").style.display = "block";
+ } else {
+ var enable_mesh_features = "False";
+ document.getElementById("liMeshTable").style.visibility = "hidden";
+ document.getElementById("liMeshTable").style.display = "none";
+ }
+
if (document.getElementById("scatterSwitch").checked == true) {
var enable_scatter = "True";
} else {
@@ -1442,7 +1484,7 @@ window.addEventListener("DOMContentLoaded", () => {
var enable_fft = "False";
}
- if (document.getElementById("500HzModeSwitch").checked == true) {
+ if (document.getElementById("250HzModeSwitch").checked == true) {
var low_bandwidth_mode = "True";
} else {
var low_bandwidth_mode = "False";
@@ -1515,7 +1557,6 @@ window.addEventListener("DOMContentLoaded", () => {
var tx_audio_level = document.getElementById("audioLevelTX").value;
var rx_buffer_size = document.getElementById("rx_buffer_size").value;
-
config.radiocontrol = radiocontrol;
config.mycall = callsign_ssid;
config.mygrid = mygrid;
@@ -1544,6 +1585,7 @@ window.addEventListener("DOMContentLoaded", () => {
config.tx_delay = tx_delay;
config.tci_ip = tci_ip;
config.tci_port = tci_port;
+ config.enable_mesh_features = enable_mesh_features;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
@@ -1593,7 +1635,8 @@ window.addEventListener("DOMContentLoaded", () => {
auto_tune,
tx_delay,
tci_ip,
- tci_port
+ tci_port,
+ enable_mesh_features
);
});
@@ -1601,6 +1644,10 @@ window.addEventListener("DOMContentLoaded", () => {
ipcRenderer.send("request-open-tnc-log");
});
+ document.getElementById("meshtable").addEventListener("click", () => {
+ ipcRenderer.send("request-open-mesh-module");
+ });
+
// stopTNC button clicked
document.getElementById("stopTNC").addEventListener("click", () => {
if (!confirm("Stop the TNC?")) return;
@@ -1610,6 +1657,7 @@ window.addEventListener("DOMContentLoaded", () => {
// btnCleanDB button clicked
document.getElementById("btnCleanDB").addEventListener("click", () => {
+ document.getElementById("divCleanDBSpinner").classList.remove("invisible");
ipcRenderer.send("request-clean-db");
});
@@ -1755,8 +1803,15 @@ window.addEventListener("DOMContentLoaded", () => {
resetSortIcon();
});
- autostart_rigctld();
+
+
+
+ autostart_rigctld();
+
+
+
});
+//End of domcontentloaded
function resetSortIcon() {
document.getElementById("hslSort").remove();
@@ -1801,6 +1856,10 @@ function connectedStation(data) {
prefix + data.dxcallsign;
}
+//Called by chat to turn off db clean spinner
+ipcRenderer.on("action-update-dbclean-spinner",() =>{
+ document.getElementById("divCleanDBSpinner").classList.add("invisible");
+});
//Listen for events caused by tnc 'tnc-message' rx
ipcRenderer.on("action-update-reception-status", (event, arg) => {
var data = arg["data"][0];
@@ -2938,6 +2997,7 @@ ipcRenderer.on("action-update-unread-messages-main", (event, data) => {
});
ipcRenderer.on("run-tnc-command", (event, arg) => {
+
if (arg.command == "save_my_call") {
sock.saveMyCall(arg.callsign);
}
@@ -3017,6 +3077,12 @@ ipcRenderer.on("run-tnc-command", (event, arg) => {
if (arg.command == "responseSharedFile") {
sock.sendResponseSharedFile(arg.dxcallsign, arg.file, arg.filedata);
}
+
+ if (arg.command == "mesh_ping") {
+ sock.sendMeshPing(arg.dxcallsign);
+ }
+
+
});
// IPC ACTION FOR AUTO UPDATER
diff --git a/gui/preload-mesh.js b/gui/preload-mesh.js
new file mode 100644
index 00000000..2834a84e
--- /dev/null
+++ b/gui/preload-mesh.js
@@ -0,0 +1,188 @@
+const path = require("path");
+const { ipcRenderer } = require("electron");
+
+// https://stackoverflow.com/a/26227660
+var appDataFolder =
+ process.env.APPDATA ||
+ (process.platform == "darwin"
+ ? process.env.HOME + "/Library/Application Support"
+ : process.env.HOME + "/.config");
+var configFolder = path.join(appDataFolder, "FreeDATA");
+var configPath = path.join(configFolder, "config.json");
+const config = require(configPath);
+
+// WINDOW LISTENER
+window.addEventListener("DOMContentLoaded", () => {
+
+ // startPing button clicked
+ document.getElementById("transmit_mesh_ping").addEventListener("click", () => {
+ var dxcallsign = document.getElementById("dxCallMesh").value.toUpperCase();
+ if (dxcallsign == "" || dxcallsign == null || dxcallsign == undefined)
+ return;
+ //pauseButton(document.getElementById("transmit_mesh_ping"), 2000);
+ ipcRenderer.send("run-tnc-command", {
+ command: "mesh_ping",
+ dxcallsign: dxcallsign,
+ });
+ });
+
+
+
+});
+
+
+ipcRenderer.on("action-update-mesh-table", (event, arg) => {
+ var routes = arg.routing_table;
+
+if (typeof routes == "undefined") {
+ return;
+ }
+
+
+ var tbl = document.getElementById("mesh-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 dxcall = document.createElement("td");
+ var dxcallText = document.createElement("span");
+ dxcallText.innerText = routes[i]["dxcall"];
+ dxcall.appendChild(dxcallText);
+
+ var router = document.createElement("td");
+ var routerText = document.createElement("span");
+ routerText.innerText = routes[i]["router"];
+ router.appendChild(routerText);
+
+ var hops = document.createElement("td");
+ var hopsText = document.createElement("span");
+ hopsText.innerText = routes[i]["hops"];
+ hops.appendChild(hopsText);
+
+ var score = document.createElement("td");
+ var scoreText = document.createElement("span");
+ scoreText.innerText = routes[i]["score"];
+ score.appendChild(scoreText);
+
+ var snr = document.createElement("td");
+ var snrText = document.createElement("span");
+ snrText.innerText = routes[i]["snr"];
+ snr.appendChild(snrText);
+
+ row.appendChild(timestamp);
+ row.appendChild(dxcall);
+ row.appendChild(router);
+ row.appendChild(hops);
+ row.appendChild(score);
+ row.appendChild(snr);
+
+
+
+ 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);
+}
+
+
+if (tbl !== null) {
+
+ // scroll to bottom of page
+ // https://stackoverflow.com/a/11715670
+ //window.scrollTo(0, document.body.scrollHeight);
+ }
+});
diff --git a/gui/sock.js b/gui/sock.js
index ec3893c9..3db27039 100644
--- a/gui/sock.js
+++ b/gui/sock.js
@@ -218,6 +218,8 @@ client.on("data", function (socketdata) {
total_bytes: data["total_bytes"],
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"],
@@ -586,6 +588,15 @@ exports.sendPing = function (dxcallsign) {
writeTncCommand(command);
};
+// Send Mesh Ping
+exports.sendMeshPing = function (dxcallsign) {
+ command =
+ '{"type" : "mesh", "command" : "ping", "dxcallsign" : "' +
+ dxcallsign +
+ '"}';
+ writeTncCommand(command);
+};
+
// Send CQ
exports.sendCQ = function () {
command = '{"type" : "broadcast", "command" : "cqcqcq"}';
@@ -851,6 +862,8 @@ exports.sendFecIsWriting = function (mycallsign) {
writeTncCommand(command);
};
+
+
// SEND FEC TO BROADCASTCHANNEL
exports.sendBroadcastChannel = function (channel, data_out, uuid) {
let checksum = "";
diff --git a/gui/src/index.html b/gui/src/index.html
index 1eec4f0d..52dee847 100644
--- a/gui/src/index.html
+++ b/gui/src/index.html
@@ -215,10 +215,18 @@
Settings
+
+
+
+
+