chat message test

This commit is contained in:
DJ2LS 2021-11-19 17:30:17 +01:00
parent 279fe7929f
commit 5218eb3909
10 changed files with 199 additions and 42 deletions

View file

@ -12,7 +12,7 @@ var appDataFolder = process.env.APPDATA || (process.platform == 'darwin' ? proce
var configFolder = path.join(appDataFolder, "FreeDATA");
var configPath = path.join(configFolder, 'config.json')
// create folder if not exists
// create config folder if not exists
if (!fs.existsSync(configFolder)) {
fs.mkdirSync(configFolder);
}
@ -40,6 +40,25 @@ if (!fs.existsSync(configPath)) {
var chatDB = path.join(configFolder, 'chatDB.json')
// create chat database file if not exists
var configContent = `
{ "chatDB" : [{
"id" : "00000000",
"timestamp" : 1234566,
"mycall" : "AA0AA",
"dxcall" : "AB0AB",
"dxgrid" : "JN1200",
"message" : "hallowelt"
}]
}
`;
if (!fs.existsSync(chatDB)) {
fs.writeFileSync(chatDB, configContent)
}
/*
// Creates receivedFiles folder if not exists
// https://stackoverflow.com/a/26227660
@ -89,26 +108,22 @@ function createWindow() {
})
*/
win.loadFile('src/index.html')
/*
data = new BrowserWindow({
chat = new BrowserWindow({
height: 900,
width: 600,
show: false,
parent: win,
webPreferences: {
preload: require.resolve('./preload-data.js'),
preload: require.resolve('./preload-chat.js'),
nodeIntegration: true,
}
})
//open dev tools
data.webContents.openDevTools({
mode: 'undocked',
activate: true,
})
data.loadFile('src/data-module.html')
data.hide()
*/
chat.loadFile('src/chat-module.html')
// Emitted when the window is closed.
win.on('closed', function() {
@ -116,24 +131,23 @@ function createWindow() {
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
win = null;
data = null;
chat = null;
})
/*
data.on('closed', function () {
chat.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
})
*/
// https://stackoverflow.com/questions/44258831/only-hide-the-window-when-closing-it-electron
/*
data.on('close', function(evt) {
chat.on('close', function(evt) {
evt.preventDefault();
data.hide()
chat.hide()
});
*/
}
app.whenReady().then(() => {
@ -144,7 +158,7 @@ app.whenReady().then(() => {
console.log("Starting Daemon")
daemonProcess = exec('./daemon', function callback(error, stdout, stderr) {
// result
console.log(stdout)
console.log(stdout)
console.log(error)
console.log(stderr)
});
@ -166,11 +180,12 @@ app.on('window-all-closed', () => {
})
// IPC HANDLER
/*
ipcMain.on('show-data-window', (event, arg) => {
data.show()
ipcMain.on('request-show-chat-window', (event, arg) => {
chat.show()
});
*/
ipcMain.on('request-update-tnc-state', (event, arg) => {
win.webContents.send('action-update-tnc-state', arg);
//data.webContents.send('action-update-tnc-state', arg);
@ -210,8 +225,5 @@ ipcMain.on('request-update-rx-buffer', (event, arg) => {
});
ipcMain.on('request-update-rx-msg-buffer', (event, arg) => {
//win.webContents.send('action-update-rx-buffer', arg);
console.log("NEW MESSAGE ARRIVED!")
console.log("WE WILL HANDLE THIS AS SOON AS WE HAVE A CHAT MODULE...")
console.log(arg)
chat.webContents.send('action-update-rx-msg-buffer', arg);
});

39
gui/package-lock.json generated
View file

@ -12,6 +12,7 @@
"bootstrap": "^5.1.0",
"chart.js": "^3.5.1",
"chartjs-plugin-annotation": "^1.0.2",
"lowdb": "^3.0.0",
"qth-locator": "^2.1.0"
},
"devDependencies": {
@ -2298,6 +2299,20 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"node_modules/lowdb": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lowdb/-/lowdb-3.0.0.tgz",
"integrity": "sha512-9KZRulmIcU8fZuWiaM0d5e2/nPnrFyXkeXVpqT+MJS+vgbgOf1EbtvgQmba8HwUFgDl1oeZR6XqEJnkJmQdKmg==",
"dependencies": {
"steno": "^2.1.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/lowercase-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
@ -2878,6 +2893,17 @@
"node": ">= 6"
}
},
"node_modules/steno": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/steno/-/steno-2.1.0.tgz",
"integrity": "sha512-mauOsiaqTNGFkWqIfwcm3y/fq+qKKaIWf1vf3ocOuTdco9XoHCO2AGF1gFYXuZFSWuP38Q8LBHBGJv2KnJSXyA==",
"engines": {
"node": "^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@ -5254,6 +5280,14 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"lowdb": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lowdb/-/lowdb-3.0.0.tgz",
"integrity": "sha512-9KZRulmIcU8fZuWiaM0d5e2/nPnrFyXkeXVpqT+MJS+vgbgOf1EbtvgQmba8HwUFgDl1oeZR6XqEJnkJmQdKmg==",
"requires": {
"steno": "^2.1.0"
}
},
"lowercase-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
@ -5709,6 +5743,11 @@
"integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==",
"dev": true
},
"steno": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/steno/-/steno-2.1.0.tgz",
"integrity": "sha512-mauOsiaqTNGFkWqIfwcm3y/fq+qKKaIWf1vf3ocOuTdco9XoHCO2AGF1gFYXuZFSWuP38Q8LBHBGJv2KnJSXyA=="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",

41
gui/preload-chat.js Normal file
View file

@ -0,0 +1,41 @@
const path = require('path')
const {
ipcRenderer
} = require('electron')
const sock = require('./sock.js');
// 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);
var chatDB = path.join(configFolder, 'chatDB.json')
// WINDOW LISTENER
window.addEventListener('DOMContentLoaded', () => {
// SEND MSG
document.getElementById("sendMessage").addEventListener("click", () => {
dxcallsign = 'DN2LS'
let Data = {
command: "sendMessage",
dxcallsign : dxcallsign.toUpperCase(),
mode : 10,
frames : 1,
data : 'hallo welt',
checksum : '123'
};
ipcRenderer.send('run-tnc-command', Data);
})
})
ipcRenderer.on('action-update-rx-buffer', (event, arg) => {
alert(arg)
})

View file

@ -436,6 +436,16 @@ advancedHamlibSettingsModal
};
ipcRenderer.send('run-tnc-command', Data);
})
// OPEN CHAT MODULE
document.getElementById("openRFChat").addEventListener("click", () => {
let Data = {
command: "openRFChat"
};
ipcRenderer.send('request-show-chat-window', Data);
})
})

View file

@ -240,7 +240,8 @@ exports.sendFile = function(dxcallsign, mode, frames, filename, filetype, data,
// Send Message
exports.sendMessage = function(dxcallsign, mode, frames, data, checksum) {
command = '{"type" : "ARQ", "command" : "sendMessage", "dxcallsign" : " ' + dxcallsign + ' ", "mode" : " ' + mode + ' ", "n_frames" : " ' + frames + ' ", "data" : ' + data + ' , "checksum" : " ' + checksum + ' ", "timestamp" : ' + Date.now() + '}'
command = '{"type" : "ARQ", "command" : "sendMessage", "dxcallsign" : "' + dxcallsign + '", "mode" : "' + mode + '", "n_frames" : "' + frames + '", "data" : "' + data + '" , "checksum" : "' + checksum + '", "timestamp" : ' + Date.now() + '}'
console.log(command)
writeTncCommand(command)
}

26
gui/src/chat-module.html Normal file
View file

@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Security-Policy" content="script-src 'self';">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
<title>FreeDATA - CHAT</title>
</head>
<body>
<!-- bootstrap -->
<script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<!-- chart.js -->
<script src="../node_modules/chart.js/dist/chart.min.js"></script>
<script src="../node_modules/chartjs-plugin-annotation/dist/chartjs-plugin-annotation.min.js"></script>
<button class="btn btn-sm btn-primary me-2" id="sendMessage" type="button">SEND MSG</button>
</body>
</html>

View file

@ -63,7 +63,7 @@
</div>
</div>
<div class="btn-toolbar" role="toolbar">
<button class="btn btn-sm btn-primary me-2" id="openRFChat" type="button" disabled>
<button class="btn btn-sm btn-primary me-2" id="openRFChat" type="button">
<strong>RF Chat</strong>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat-left-text-fill" viewBox="0 0 16 16">
<path d="M0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H4.414a1 1 0 0 0-.707.293L.854 15.146A.5.5 0 0 1 0 14.793V2zm3.5 1a.5.5 0 0 0 0 1h9a.5.5 0 0 0 0-1h-9zm0 2.5a.5.5 0 0 0 0 1h9a.5.5 0 0 0 0-1h-9zm0 2.5a.5.5 0 0 0 0 1h5a.5.5 0 0 0 0-1h-5z"/>
@ -865,9 +865,9 @@
<div class="input-group input-group-sm">
<span class="input-group-text" id="basic-addon1">Mode</span>
<select class="form-select form-select-sm" aria-label=".form-select-sm" id="datamode">
<option value="14">low SNR (DC0)</option>
<option selected value="10">high SNR (DC1)</option>
<option value="12">med SNR (DC3)</option>
<!--<option value="14">low SNR (DC0)</option>-->
<option selected value="10">HIGH SNR (DC1)</option>
<option value="12">MED SNR (DC3)</option>
</select>
</div>
</div>

View file

@ -85,13 +85,15 @@ def arq_data_received(data_in, bytes_per_frame):
RX_N_FRAMES_PER_DATA_FRAME = int.from_bytes(bytes(data_in[4:6]), "big") # get total number of frames
static.TOTAL_BYTES = RX_N_FRAMES_PER_DATA_FRAME * RX_PAYLOAD_PER_ARQ_FRAME # calculate total bytes
arq_percent_burst = int((RX_N_FRAME_OF_BURST / RX_N_FRAMES_PER_BURST) * 100)
##arq_percent_burst = int((RX_N_FRAME_OF_BURST / RX_N_FRAMES_PER_BURST) * 100)
#arq_percent_frame = int(((RX_N_FRAME_OF_DATA_FRAME) / RX_N_FRAMES_PER_DATA_FRAME) * 100)
calculate_transfer_rate_rx(RX_N_FRAMES_PER_DATA_FRAME, RX_N_FRAME_OF_DATA_FRAME, RX_START_OF_TRANSMISSION, RX_PAYLOAD_PER_ARQ_FRAME)
static.INFO.append("ARQ;RECEIVING")
logging.log(24, "ARQ | RX | " + str(DATA_CHANNEL_MODE) + " | F:[" + str(RX_N_FRAME_OF_BURST) + "/" + str(RX_N_FRAMES_PER_BURST) + "] [" + str(arq_percent_burst).zfill(3) + "%] T:[" + str(RX_N_FRAME_OF_DATA_FRAME) + "/" + str(RX_N_FRAMES_PER_DATA_FRAME) + "] [" + str(int(static.ARQ_TRANSMISSION_PERCENT)).zfill(3) + "%] [SNR:" + str(static.SNR) + "]")
frame_progress = str(RX_N_FRAME_OF_BURST) + "/" + str(RX_N_FRAMES_PER_BURST)
total_frame_progress = str(RX_N_FRAME_OF_DATA_FRAME) + "/" + str(RX_N_FRAMES_PER_DATA_FRAME)
transmission_percent = str(static.ARQ_TRANSMISSION_PERCENT).zfill(3)
structlog.get_logger("structlog").info("[TNC] ARQ RX DATA", mode=DATA_CHANNEL_MODE, frames=frame_progress, percent=transmission_percent, frames_total=total_frame_progress)
# allocate ARQ_static.RX_FRAME_BUFFER as a list with "None" if not already done. This should be done only once per burst!
# here we will save the N frame of a data frame to N list position so we can explicit search for it
@ -270,7 +272,7 @@ def arq_data_received(data_in, bytes_per_frame):
helpers.wait(0.5)
while not modem.transmit_signalling(ack_frame, 2):
while not modem.transmit_signalling(ack_frame, 3):
time.sleep(0.01)
calculate_transfer_rate_rx(RX_N_FRAMES_PER_DATA_FRAME, RX_N_FRAME_OF_DATA_FRAME, RX_START_OF_TRANSMISSION, RX_PAYLOAD_PER_ARQ_FRAME)
@ -732,7 +734,7 @@ def arq_received_data_channel_opener(data_in):
connection_frame[3:9] = static.MYCALLSIGN
connection_frame[12:13] = bytes([mode])
while not modem.transmit_signalling(connection_frame, 1):
while not modem.transmit_signalling(connection_frame, 2):
time.sleep(0.01)
structlog.get_logger("structlog").info("[TNC] DATA [" + str(static.MYCALLSIGN, 'utf-8') + "]>>|<<[" + str(static.DXCALLSIGN, 'utf-8') + "]", snr=static.SNR, mode=mode)

View file

@ -545,6 +545,7 @@ class RF():
self.get_scatter(datac0_freedv)
if sync != 0 and nbytes != 0:
print("----------DECODE----------------")
# clear all buffers for be ready with clean audio data
# we need to be carefull and only cleaning buffer if we reached the last frame of a burst
datac0_buffer = bytes()
@ -568,7 +569,7 @@ class RF():
sync = self.c_lib.freedv_get_rx_status(datac1_freedv)
if sync != 0 and nbytes != 0:
print("----------DECODE----------------")
frame = int.from_bytes(bytes(datac1_bytes_out[:1]), "big") - 10
n_frames_per_burst = int.from_bytes(bytes(datac1_bytes_out[1:2]), "big")
print("frame: {0}, N_frames_per_burst: {1}".format(frame, n_frames_per_burst))
@ -591,7 +592,7 @@ class RF():
sync = self.c_lib.freedv_get_rx_status(datac3_freedv)
if sync != 0 and nbytes != 0:
print("----------DECODE----------------")
# calculate snr and scatter
self.get_scatter(datac3_freedv)
self.calculate_snr(datac3_freedv)

View file

@ -137,7 +137,32 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
ARQ_DATA_THREAD = threading.Thread(target=data_handler.open_dc_and_transmit, args=[data_out, mode, n_frames], name="ARQ_DATA")
ARQ_DATA_THREAD.start()
# asyncio.run(data_handler.arq_transmit(data_out))
# send message
if received_json["type"] == 'ARQ' and received_json["command"] == "sendMessage":
static.TNC_STATE = 'BUSY'
print(received_json)
# on a new transmission we reset the timer
static.ARQ_START_OF_TRANSMISSION = int(time.time())
dxcallsign = received_json["dxcallsign"]
mode = int(received_json["mode"])
n_frames = int(received_json["n_frames"])
data = received_json["data"]
checksum = received_json["checksum"]
static.DXCALLSIGN = bytes(dxcallsign, 'utf-8')
static.DXCALLSIGN_CRC8 = helpers.get_crc_8(
static.DXCALLSIGN)
rawdata = {"datatype": "message","data": data, "checksum": checksum}
dataframe = json.dumps(rawdata)
data_out = bytes(dataframe, 'utf-8')
ARQ_DATA_THREAD = threading.Thread(target=data_handler.open_dc_and_transmit, args=[data_out, mode, n_frames], name="ARQ_DATA")
ARQ_DATA_THREAD.start()
if received_json["type"] == 'ARQ' and received_json["command"] == "stopTransmission":
print(" >>> STOPPING TRANSMISSION <<<")
structlog.get_logger("structlog").warning("[TNC] Stopping transmission!")