Prettified Code!

This commit is contained in:
DJ2LS 2023-02-11 21:49:07 +00:00 committed by GitHub Action
parent f540192888
commit 6bf8c43d60
26 changed files with 11529 additions and 7556 deletions

View File

@ -1,10 +1,9 @@
---
name: Bug report
about: Create a report to help us improve FreeDATA
title: ''
title: ""
labels: bug
assignees: ''
assignees: ""
---
**Describe the bug**
@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
@ -27,6 +27,7 @@ https://wiki.freedata.app/en/usage/logging
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Version [e.g. 22]
- Platform [Raspberry Pi, Desktop]

View File

@ -1,10 +1,9 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
title: ""
labels: feature request
assignees: ''
assignees: ""
---
**Is your feature request related to a problem? Please describe.**

View File

@ -1,4 +1,5 @@
# FreeDATA
My attempt to create a free and open-source TNC with a GUI for [codec2](https://github.com/drowe67/codec2) with the idea of sending messages and data from one network based application.
[mailing-list](https://groups.io/g/freedata)
@ -8,10 +9,10 @@ My attempt to create a free and open-source TNC with a GUI for [codec2](https://
![Build](https://github.com/DJ2LS/FreeDATA/actions/workflows/build_multiplatform.yml/badge.svg)
[![CodeFactor](https://www.codefactor.io/repository/github/dj2ls/freedata/badge)](https://www.codefactor.io/repository/github/dj2ls/freedata)
Please keep in mind, this project is still under development with many issues which need to be solved.
### existing/planned TNC features
- [x] network based
- [x] raw data transfer
- [x] fft output
@ -24,7 +25,9 @@ Please keep in mind, this project is still under development with many issues wh
- [x] channel measurement
- [ ] hybrid ARQ
- [ ] tbc...
### existing/planned Chat features
- [x] chat messages
- [x] file transfer
- [x] file transfer with chat message
@ -38,18 +41,21 @@ Please keep in mind, this project is still under development with many issues wh
- [ ] tbc...
## Data Preview
![preview](https://github.com/DJ2LS/FreeDATA/blob/main/documentation/data_preview.gif?raw=true "Preview")
## Chat Preview
![preview](https://github.com/DJ2LS/FreeDATA/blob/main/documentation/chat_preview_fast.gif?raw=true "Preview")
## Installation
Please check the [wiki](https://wiki.freedata.app) for installation instructions
Please check the ['Releases'](https://github.com/DJ2LS/FreeDATA/releases) section for downloading precompiled builds
## Credits
* David Rowe and the FreeDV team for developing the modem and libraries -
- David Rowe and the FreeDV team for developing the modem and libraries -
FreeDV Codec 2 : https://github.com/drowe67/codec2
* xssfox, her repository helped a lot in an early stage of development -
- xssfox, her repository helped a lot in an early stage of development -
xssfox : https://github.com/xssfox/freedv-tnc

View File

@ -1,21 +1,25 @@
# FreeDATA - DAEMON network documentation
## GET DAEMON STATE
#### Description:
Get the current daemon state
#### Parameters
- Type: GET
- Command: DAEMON_STATE
- Parameter: --- (str)
#### Example
```
{"type" : "GET", "command" : "DAEMON_STATE"}
```
#### Returns
```
{
"COMMAND": "DAEMON_STATE",
@ -31,46 +35,52 @@ Get the current daemon state
}
```
## SET CALLSIGN
#### Description:
Save your callsign to the daemon
#### Parameters
- Type: SET
- Command: MYCALLSIGN
- Parameter: callsign (str)
- timestamp: unix timestamp (str)
#### Example
```
{"type" : "SET", "command": "MYCALLSIGN" , "parameter": "<callsign>", "timestamp" : "123456789"}
```
## SET GRIDSQUARE
#### Description:
Save your gridsquare/maidenhead-locator to the daemon
#### Parameters
- Type: SET
- Command: MYGRID
- Parameter: gridsquare (str)
- timestamp: unix timestamp (str)
#### Example
```
{"type" : "SET", "command": "MYGRID" , "parameter": "<gridsquare>", "timestamp" : "123456789"}
```
## TEST HAMLIB
#### Description:
Test your hamlib settings
#### Parameters
- Type: GET
- Command: TEST_HAMLIB
- Parameter: obj
@ -85,6 +95,7 @@ Test your hamlib settings
- timestamp: unix timestamp (str)
#### Example
```
{
"type": "GET",
@ -102,12 +113,14 @@ Test your hamlib settings
}
```
## START TNC
#### Description:
Start the tnc process
#### Parameters
- Type: GET
- Command: TEST_HAMLIB
- Parameter: obj
@ -125,6 +138,7 @@ Start the tnc process
- handshake
#### Example
```
{
type: 'SET',
@ -148,23 +162,19 @@ Start the tnc process
```
## STOP TNC
#### Description:
Stop the tnc process
#### Parameters
- Type: SET
- Command: STOPTNC
- Parameter: ---
#### Example
```
{"type" : "SET", "command": "STOPTNC" , "parameter": "---" }
```

View File

@ -1,74 +1,73 @@
var net = require('net');
const path = require('path')
const {
ipcRenderer
} = require('electron')
const log = require('electron-log');
const daemonLog = log.scope('daemon');
var net = require("net");
const path = require("path");
const { ipcRenderer } = require("electron");
const log = require("electron-log");
const daemonLog = log.scope("daemon");
// https://stackoverflow.com/a/26227660
var appDataFolder = process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME + "/.config")
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')
var configPath = path.join(configFolder, "config.json");
const config = require(configPath);
var daemon = new net.Socket();
var socketchunk = ''; // Current message, per connection.
var socketchunk = ""; // Current message, per connection.
// global to keep track of daemon connection error emissions
var daemonShowConnectStateError = 1
var daemonShowConnectStateError = 1;
// global for storing ip information
var daemon_port = config.daemon_port;
var daemon_host = config.daemon_host;
setTimeout(connectDAEMON, 500)
setTimeout(connectDAEMON, 500);
function connectDAEMON() {
if (daemonShowConnectStateError == 1) {
daemonLog.info('connecting to daemon');
daemonLog.info("connecting to daemon");
}
//clear message buffer after reconnecting or initial connection
socketchunk = '';
socketchunk = "";
if (config.tnclocation == 'localhost') {
daemon.connect(3001, '127.0.0.1')
if (config.tnclocation == "localhost") {
daemon.connect(3001, "127.0.0.1");
} else {
daemon.connect(daemon_port, daemon_host)
daemon.connect(daemon_port, daemon_host);
}
//client.setTimeout(5000);
}
daemon.on('connect', function(err) {
daemonLog.info('daemon connection established');
daemon.on("connect", function (err) {
daemonLog.info("daemon connection established");
let Data = {
daemon_connection: daemon.readyState,
};
ipcRenderer.send('request-update-daemon-connection', Data);
ipcRenderer.send("request-update-daemon-connection", Data);
daemonShowConnectStateError = 1
})
daemonShowConnectStateError = 1;
});
daemon.on('error', function(err) {
daemon.on("error", function (err) {
if (daemonShowConnectStateError == 1) {
daemonLog.error('daemon connection error');
daemonLog.info('Make sure the daemon is started.');
daemonLog.error("daemon connection error");
daemonLog.info("Make sure the daemon is started.");
daemonLog.info('Run "python daemon.py" in the tnc directory.');
daemonLog.debug(err)
daemonLog.debug(err);
daemonShowConnectStateError = 0
daemonShowConnectStateError = 0;
}
setTimeout(connectDAEMON, 500)
setTimeout(connectDAEMON, 500);
daemon.destroy();
let Data = {
daemon_connection: daemon.readyState,
};
ipcRenderer.send('request-update-daemon-connection', Data);
ipcRenderer.send("request-update-daemon-connection", Data);
});
/*
@ -82,127 +81,105 @@ client.on('close', function(data) {
});
*/
daemon.on('end', function(data) {
daemonLog.warn('daemon connection ended');
daemon.on("end", function (data) {
daemonLog.warn("daemon connection ended");
daemon.destroy();
setTimeout(connectDAEMON, 500)
setTimeout(connectDAEMON, 500);
let Data = {
daemon_connection: daemon.readyState,
};
ipcRenderer.send('request-update-daemon-connection', Data);
ipcRenderer.send("request-update-daemon-connection", Data);
});
//exports.writeCommand = function(command){
writeDaemonCommand = function (command) {
// we use the writingCommand function to update our TCPIP state because we are calling this function a lot
// if socket opened, we are able to run commands
if (daemon.readyState == 'open') {
if (daemon.readyState == "open") {
//uiMain.setDAEMONconnection('open')
daemon.write(command + '\n');
daemon.write(command + "\n");
}
if (daemon.readyState == 'closed') {
if (daemon.readyState == "closed") {
//uiMain.setDAEMONconnection('closed')
}
if (daemon.readyState == 'opening') {
if (daemon.readyState == "opening") {
//uiMain.setDAEMONconnection('opening')
}
let Data = {
daemon_connection: daemon.readyState,
};
ipcRenderer.send('request-update-daemon-connection', Data);
}
ipcRenderer.send("request-update-daemon-connection", Data);
};
// "https://stackoverflow.com/questions/9070700/nodejs-net-createserver-large-amount-of-data-coming-in"
daemon.on('data', function(socketdata) {
daemon.on("data", function (socketdata) {
/*
inspired by:
stackoverflow.com questions 9070700 nodejs-net-createserver-large-amount-of-data-coming-in
*/
socketdata = socketdata.toString('utf8'); // convert data to string
socketchunk += socketdata// append data to buffer so we can stick long data together
socketdata = socketdata.toString("utf8"); // convert data to string
socketchunk += socketdata; // append data to buffer so we can stick long data together
// check if we received begin and end of json data
if (socketchunk.startsWith('{"') && socketchunk.endsWith('"}\n')) {
var data = ''
var data = "";
// split data into chunks if we received multiple commands
socketchunk = socketchunk.split("\n");
data = JSON.parse(socketchunk[0])
data = JSON.parse(socketchunk[0]);
// search for empty entries in socketchunk and remove them
for (i = 0; i < socketchunk.length; i++) {
if (socketchunk[i] === ''){
if (socketchunk[i] === "") {
socketchunk.splice(i, 1);
}
}
//iterate through socketchunks array to execute multiple commands in row
for (i = 0; i < socketchunk.length; i++) {
//check if data is not empty
if (socketchunk[i].length > 0) {
//try to parse JSON
try {
data = JSON.parse(socketchunk[i])
data = JSON.parse(socketchunk[i]);
} catch (e) {
console.log(e); // "SyntaxError
daemonLog.error(e);
daemonLog.debug(socketchunk[i])
socketchunk = ''
daemonLog.debug(socketchunk[i]);
socketchunk = "";
}
}
}
if (data['command'] == 'daemon_state') {
if (data["command"] == "daemon_state") {
let Data = {
input_devices: data['input_devices'],
output_devices: data['output_devices'],
python_version: data['python_version'],
hamlib_version: data['hamlib_version'],
serial_devices: data['serial_devices'],
tnc_running_state: data['daemon_state'][0]['status'],
ram_usage: data['ram'],
cpu_usage: data['cpu'],
version: data['version'],
input_devices: data["input_devices"],
output_devices: data["output_devices"],
python_version: data["python_version"],
hamlib_version: data["hamlib_version"],
serial_devices: data["serial_devices"],
tnc_running_state: data["daemon_state"][0]["status"],
ram_usage: data["ram"],
cpu_usage: data["cpu"],
version: data["version"],
};
ipcRenderer.send('request-update-daemon-state', Data);
ipcRenderer.send("request-update-daemon-state", Data);
}
if (data['command'] == 'test_hamlib') {
if (data["command"] == "test_hamlib") {
let Data = {
hamlib_result: data['result'],
hamlib_result: data["result"],
};
ipcRenderer.send('request-update-hamlib-test', Data);
ipcRenderer.send("request-update-hamlib-test", Data);
}
}
//finally delete message buffer
socketchunk = '';
socketchunk = "";
}
});
@ -214,18 +191,47 @@ function hexToBytes(hex) {
exports.getDaemonState = function () {
//function getDaemonState(){
command = '{"type" : "get", "command" : "daemon_state"}'
writeDaemonCommand(command)
}
command = '{"type" : "get", "command" : "daemon_state"}';
writeDaemonCommand(command);
};
// START TNC
// ` `== multi line string
exports.startTNC = function(mycall, mygrid, rx_audio, tx_audio, radiocontrol, devicename, deviceport, pttprotocol, pttport, serialspeed, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port, enable_fft, enable_scatter, low_bandwidth_mode, tuning_range_fmin, tuning_range_fmax, enable_fsk, tx_audio_level, respond_to_cq, rx_buffer_size, enable_explorer, explorer_stats, auto_tune) {
exports.startTNC = function (
mycall,
mygrid,
rx_audio,
tx_audio,
radiocontrol,
devicename,
deviceport,
pttprotocol,
pttport,
serialspeed,
data_bits,
stop_bits,
handshake,
rigctld_ip,
rigctld_port,
enable_fft,
enable_scatter,
low_bandwidth_mode,
tuning_range_fmin,
tuning_range_fmax,
enable_fsk,
tx_audio_level,
respond_to_cq,
rx_buffer_size,
enable_explorer,
explorer_stats,
auto_tune
) {
var json_command = JSON.stringify({
type: 'set',
command: 'start_tnc',
parameter: [{
type: "set",
command: "start_tnc",
parameter: [
{
mycall: mycall,
mygrid: mygrid,
rx_audio: rx_audio,
@ -252,28 +258,40 @@ exports.startTNC = function(mycall, mygrid, rx_audio, tx_audio, radiocontrol, de
rx_buffer_size: rx_buffer_size,
enable_explorer: enable_explorer,
enable_stats: explorer_stats,
enable_auto_tune: auto_tune
}]
})
enable_auto_tune: auto_tune,
},
],
});
daemonLog.debug(json_command);
writeDaemonCommand(json_command)
}
writeDaemonCommand(json_command);
};
// STOP TNC
exports.stopTNC = function () {
command = '{"type" : "set", "command": "stop_tnc" , "parameter": "---" }'
writeDaemonCommand(command)
}
command = '{"type" : "set", "command": "stop_tnc" , "parameter": "---" }';
writeDaemonCommand(command);
};
// TEST HAMLIB
exports.testHamlib = function(radiocontrol, devicename, deviceport, serialspeed, pttprotocol, pttport, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port) {
exports.testHamlib = function (
radiocontrol,
devicename,
deviceport,
serialspeed,
pttprotocol,
pttport,
data_bits,
stop_bits,
handshake,
rigctld_ip,
rigctld_port
) {
var json_command = JSON.stringify({
type: 'get',
command: 'test_hamlib',
parameter: [{
type: "get",
command: "test_hamlib",
parameter: [
{
radiocontrol: radiocontrol,
devicename: devicename,
deviceport: deviceport,
@ -284,28 +302,31 @@ exports.testHamlib = function(radiocontrol, devicename, deviceport, serialspeed,
stop_bits: stop_bits,
handshake: handshake,
rigctld_port: rigctld_port,
rigctld_ip: rigctld_ip
}]
})
rigctld_ip: rigctld_ip,
},
],
});
daemonLog.debug(json_command);
writeDaemonCommand(json_command)
}
writeDaemonCommand(json_command);
};
//Save myCall
exports.saveMyCall = function (callsign) {
command = '{"type" : "set", "command": "mycallsign" , "parameter": "' + callsign + '"}'
writeDaemonCommand(command)
}
command =
'{"type" : "set", "command": "mycallsign" , "parameter": "' +
callsign +
'"}';
writeDaemonCommand(command);
};
// Save myGrid
exports.saveMyGrid = function (grid) {
command = '{"type" : "set", "command": "mygrid" , "parameter": "' + grid + '"}'
writeDaemonCommand(command)
}
command =
'{"type" : "set", "command": "mygrid" , "parameter": "' + grid + '"}';
writeDaemonCommand(command);
};
ipcRenderer.on('action-update-daemon-ip', (event, arg) => {
ipcRenderer.on("action-update-daemon-ip", (event, arg) => {
daemon.destroy();
let Data = {
busy_state: "-",
@ -314,9 +335,9 @@ ipcRenderer.on('action-update-daemon-ip', (event, arg) => {
frequency: "-",
mode: "-",
bandwidth: "-",
dbfs_level: 0
dbfs_level: 0,
};
ipcRenderer.send('request-update-tnc-state', Data);
ipcRenderer.send("request-update-tnc-state", Data);
daemon_port = arg.port;
daemon_host = arg.adress;
connectDAEMON();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +1,86 @@
const path = require('path');
const {ipcRenderer} = require('electron');
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 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')
var configPath = path.join(configFolder, "config.json");
const config = require(configPath);
// WINDOW LISTENER
window.addEventListener('DOMContentLoaded', () => {
document.getElementById('enable_filter_info').addEventListener('click', () => {
if (document.getElementById('enable_filter_info').checked){
display_class("table-info", true)
window.addEventListener("DOMContentLoaded", () => {
document
.getElementById("enable_filter_info")
.addEventListener("click", () => {
if (document.getElementById("enable_filter_info").checked) {
display_class("table-info", true);
} else {
display_class("table-info", false)
display_class("table-info", false);
}
})
});
document.getElementById('enable_filter_debug').addEventListener('click', () => {
if (document.getElementById('enable_filter_debug').checked){
display_class("table-debug", true)
document
.getElementById("enable_filter_debug")
.addEventListener("click", () => {
if (document.getElementById("enable_filter_debug").checked) {
display_class("table-debug", true);
} else {
display_class("table-debug", false)
display_class("table-debug", false);
}
})
});
document.getElementById('enable_filter_warning').addEventListener('click', () => {
if (document.getElementById('enable_filter_warning').checked){
display_class("table-warning", true)
document
.getElementById("enable_filter_warning")
.addEventListener("click", () => {
if (document.getElementById("enable_filter_warning").checked) {
display_class("table-warning", true);
} else {
display_class("table-warning", false)
display_class("table-warning", false);
}
})
});
document.getElementById('enable_filter_error').addEventListener('click', () => {
if (document.getElementById('enable_filter_error').checked){
display_class("table-danger", true)
document
.getElementById("enable_filter_error")
.addEventListener("click", () => {
if (document.getElementById("enable_filter_error").checked) {
display_class("table-danger", true);
} else {
display_class("table-danger", false)
display_class("table-danger", false);
}
})
})
});
});
function display_class(class_name, state) {
var collection = document.getElementsByClassName(class_name);
console.log(collection)
console.log(collection);
for (let i = 0; i < collection.length; i++) {
if (state == true) {
collection[i].style.display = "table-row";
} else {
collection[i].style.display = "None";
}
}
}
ipcRenderer.on('action-update-log', (event, arg) => {
var entry = arg.entry
ipcRenderer.on("action-update-log", (event, arg) => {
var entry = arg.entry;
// remove ANSI characters from string, caused by color logging
// https://stackoverflow.com/a/29497680
entry = entry.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,'')
entry = entry.replace(
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
""
);
var tbl = document.getElementById("log");
var row = document.createElement("tr");
var timestamp = document.createElement("td");
var timestampText = document.createElement('span');
var timestampText = document.createElement("span");
//datetime = new Date();
//timestampText.innerText = datetime.toISOString();
@ -78,36 +88,36 @@ ipcRenderer.on('action-update-log', (event, arg) => {
timestamp.appendChild(timestampText);
var type = document.createElement("td");
var typeText = document.createElement('span');
var typeText = document.createElement("span");
// typeText.innerText = entry.slice(10, 30).match(/[\[](.*)[^\]]/g);
console.log(entry.match(/\[[^\]]+\]/g))
console.log(entry.match(/\[[^\]]+\]/g));
try {
typeText.innerText = entry.match(/\[[^\]]+\]/g)[0];
} catch (e) {
typeText.innerText = '-'
typeText.innerText = "-";
}
// let res = str.match(/[\[](.*)[^\]]/g);
type.appendChild(typeText);
var area = document.createElement("td");
var areaText = document.createElement('span');
var areaText = document.createElement("span");
//areaText.innerText = entry.slice(10, 50).match(/[\] \[](.*)[^\]]/g);
//areaText.innerText = entry.match(/\[[^\]]+\]/g)[1];
try {
areaText.innerText = entry.match(/\[[^\]]+\]/g)[1];
} catch (e) {
areaText.innerText = '-'
areaText.innerText = "-";
}
area.appendChild(areaText);
var logEntry = document.createElement("td");
var logEntryText = document.createElement('span');
try{logEntryText.innerText = entry.split("]")[2];
var logEntryText = document.createElement("span");
try {
logEntryText.innerText = entry.split("]")[2];
} catch (e) {
logEntryText.innerText = "-";
}
@ -124,69 +134,53 @@ ipcRenderer.on('action-update-log', (event, arg) => {
row.classList.add("table-secondary");
}
*/
if (typeText.innerText.includes('info')) {
if (typeText.innerText.includes("info")) {
row.classList.add("table-info");
}
if (typeText.innerText.includes('debug')) {
if (typeText.innerText.includes("debug")) {
row.classList.add("table-secondary");
}
if (typeText.innerText.includes('warning')) {
if (typeText.innerText.includes("warning")) {
row.classList.add("table-warning");
}
if (typeText.innerText.includes('error')) {
if (typeText.innerText.includes("error")) {
row.classList.add("table-danger");
}
if (document.getElementById('enable_filter_info').checked) {
row.style.display = "table-row"
display_class("table-info", true)
if (document.getElementById("enable_filter_info").checked) {
row.style.display = "table-row";
display_class("table-info", true);
} else {
row.style.display = "None"
display_class("table-info", false)
row.style.display = "None";
display_class("table-info", false);
}
if (document.getElementById('enable_filter_debug').checked) {
row.style.display = "table-row"
display_class("table-secondary", true)
if (document.getElementById("enable_filter_debug").checked) {
row.style.display = "table-row";
display_class("table-secondary", true);
} else {
row.style.display = "None"
display_class("table-secondary", false)
row.style.display = "None";
display_class("table-secondary", false);
}
if (document.getElementById('enable_filter_warning').checked) {
row.style.display = "table-row"
display_class("table-warning", true)
if (document.getElementById("enable_filter_warning").checked) {
row.style.display = "table-row";
display_class("table-warning", true);
} else {
row.style.display = "None"
display_class("table-warning", false)
row.style.display = "None";
display_class("table-warning", false);
}
if (document.getElementById('enable_filter_error').checked) {
row.style.display = "table-row"
display_class("table-danger", true)
if (document.getElementById("enable_filter_error").checked) {
row.style.display = "table-row";
display_class("table-danger", true);
} else {
row.style.display = "None"
display_class("table-danger", false)
row.style.display = "None";
display_class("table-danger", false);
}
tbl.appendChild(row);
// scroll to bottom of page
// https://stackoverflow.com/a/11715670
window.scrollTo(0, document.body.scrollHeight);
})
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,20 @@
<!doctype html>
<!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';">
<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" id="bootstrap_theme" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="../node_modules/bootstrap-icons/font/bootstrap-icons.css">
<link
rel="stylesheet"
id="bootstrap_theme"
href="../node_modules/bootstrap/dist/css/bootstrap.min.css"
/>
<link
rel="stylesheet"
href="../node_modules/bootstrap-icons/font/bootstrap-icons.css"
/>
<!-- Custom CSS -->
<link rel="stylesheet" type="text/css" href="styles.css" />
<title>FreeDATA - CHAT</title>
@ -21,10 +27,24 @@
<script src="../node_modules/chart.js/dist/chart.umd.js"></script>
<!--<script src="../node_modules/chartjs-plugin-annotation/dist/chartjs-plugin-annotation.min.js"></script>-->
<!--<script type="module" src="../node_modules/emoji-picker-element/index.js"></script>-->
<script type="module" src="../node_modules/emoji-picker-element/picker.js"></script>
<script type="module" src="../node_modules/emoji-picker-element/database.js"></script>
<div class="position-absolute container w-100 h-100 bottom-0 end-0 mb-5" style="z-index:100; display: none" id="emojipickercontainer">
<emoji-picker locale="en" class="position-absolute bottom-0 end-0 p-1 mb-2" data-source="../node_modules/emoji-picker-element-data/en/emojibase/data.json"></emoji-picker>
<script
type="module"
src="../node_modules/emoji-picker-element/picker.js"
></script>
<script
type="module"
src="../node_modules/emoji-picker-element/database.js"
></script>
<div
class="position-absolute container w-100 h-100 bottom-0 end-0 mb-5"
style="z-index: 100; display: none"
id="emojipickercontainer"
>
<emoji-picker
locale="en"
class="position-absolute bottom-0 end-0 p-1 mb-2"
data-source="../node_modules/emoji-picker-element-data/en/emojibase/data.json"
></emoji-picker>
</div>
<div class="container-fluid">
<div class="row h-100">
@ -32,52 +52,129 @@
<! ------Chats area ---------------------------------------------------------------------->
<div class="container-fluid m-0 p-0">
<div class="input-group bottom-0 m-0 w-100">
<input class="form-control w-50" maxlength="9" style="text-transform:uppercase;" id="chatModuleNewDxCall" placeholder="DX CALL">
<button class="btn btn-sm btn-success w-50" id="createNewChatButton" type="button"><i class="bi bi-pencil-square" style="font-size: 1.2rem;"></i></button>
<input
class="form-control w-50"
maxlength="9"
style="text-transform: uppercase"
id="chatModuleNewDxCall"
placeholder="DX CALL"
/>
<button
class="btn btn-sm btn-success w-50"
id="createNewChatButton"
type="button"
>
<i class="bi bi-pencil-square" style="font-size: 1.2rem"></i>
</button>
</div>
</div>
<hr class="m-2">
<hr class="m-2" />
<div class="overflow-auto vh-100">
<div class="list-group overflow-auto" id="list-tab" role="tablist" style="height: calc(100vh - 70px)"> </div>
<div
class="list-group overflow-auto"
id="list-tab"
role="tablist"
style="height: calc(100vh - 70px)"
></div>
</div>
</div>
<div class="col-8 border vh-100 p-0">
<! ------ chat navbar ---------------------------------------------------------------------->
<div class="container-fluid m-2 p-0">
<div class="input-group bottom-0">
<button class="btn btn-sm btn-secondary me-2" id="ping" type="button">Ping</button>
<button id="chatSettingsDropDown" type="button" class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false"> <i class="bi bi-three-dots-vertical"></i> </button>
<button
class="btn btn-sm btn-secondary me-2"
id="ping"
type="button"
>
Ping
</button>
<button
id="chatSettingsDropDown"
type="button"
class="btn btn-outline-secondary dropdown-toggle"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<i class="bi bi-three-dots-vertical"></i>
</button>
<ul class="dropdown-menu" aria-labelledby="chatSettingsDropDown">
<li><a class="dropdown-item bg-danger text-white" id="delete_selected_chat" href="#">Delete chat</a></li>
<li>
<a
class="dropdown-item bg-danger text-white"
id="delete_selected_chat"
href="#"
>Delete chat</a
>
</li>
</ul>
</div>
</div>
<hr class="m-0">
<hr class="m-0" />
<! ------messages area ---------------------------------------------------------------------->
<div class="container overflow-auto" id="message-container" style="height: calc(100% - 150px);">
<div
class="container overflow-auto"
id="message-container"
style="height: calc(100% - 150px)"
>
<div class="tab-content" id="nav-tabContent"></div>
<!--<div class="container position-absolute bottom-0">--></div>
<!--<div class="container position-absolute bottom-0">-->
</div>
<!-- </div>-->
<div class="container-fluid mt-2 p-0">
<input type="checkbox" id="expand_textarea" class="btn-check" autocomplete="off">
<label class="btn d-flex justify-content-center" id="expand_textarea_label" for="expand_textarea"><i id="expand_textarea_button" class="bi bi-chevron-compact-up"></i></label>
<input
type="checkbox"
id="expand_textarea"
class="btn-check"
autocomplete="off"
/>
<label
class="btn d-flex justify-content-center"
id="expand_textarea_label"
for="expand_textarea"
><i
id="expand_textarea_button"
class="bi bi-chevron-compact-up"
></i
></label>
<div class="input-group bottom-0 w-100">
<!--<input class="form-control" maxlength="8" style="max-width: 6rem; text-transform:uppercase; display:none" id="chatModuleDxCall" placeholder="DX CALL"></input>-->
<!--<button class="btn btn-sm btn-primary me-2" id="emojipickerbutton" type="button">--><i id="emojipickerbutton" class="bi bi-emoji-smile m-1" style="font-size: 1.5rem; color: grey;"></i><!--</button>-->
<!--<button class="btn btn-sm btn-primary me-2" id="emojipickerbutton" type="button">--><i
id="emojipickerbutton"
class="bi bi-emoji-smile m-1"
style="font-size: 1.5rem; color: grey"
></i
><!--</button>-->
<!--<input class="form-control rounded-pill m-1 p-1" id="chatModuleMessage" placeholder="Message - Send with [Enter]"></input>-->
<textarea class="form-control m-1 p-1" rows="1" id="chatModuleMessage" placeholder="Message - Send with [Enter]"></textarea>
<textarea
class="form-control m-1 p-1"
rows="1"
id="chatModuleMessage"
placeholder="Message - Send with [Enter]"
></textarea>
<!--<button class="btn btn-sm btn-primary me-2" style="width: 3rem" id="selectFilesButton" type="button"><i class="bi bi-paperclip" style="font-size: 1.2rem; color: white;"></i></button>--><i class="bi bi-paperclip m-1" style="font-size: 1.5rem; color: grey;" id="selectFilesButton"></i>
<button class="btn btn-sm btn-secondary me-2" style="width: 5rem; display: none" id="sendMessage" type="button"><i class="bi bi-send" style="font-size: 1.2rem; color: white;"></i></button>
<!--<button class="btn btn-sm btn-primary me-2" style="width: 3rem" id="selectFilesButton" type="button"><i class="bi bi-paperclip" style="font-size: 1.2rem; color: white;"></i></button>--><i
class="bi bi-paperclip m-1"
style="font-size: 1.5rem; color: grey"
id="selectFilesButton"
></i>
<button
class="btn btn-sm btn-secondary me-2"
style="width: 5rem; display: none"
id="sendMessage"
type="button"
>
<i
class="bi bi-send"
style="font-size: 1.2rem; color: white"
></i>
</button>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,12 +1,15 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<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">
<link
rel="stylesheet"
href="../node_modules/bootstrap/dist/css/bootstrap.min.css"
/>
<title>Send & Receive Data</title>
</head>
<body>
@ -18,8 +21,14 @@
<div class="card-header">Select data</div>
<div class="card-body">
<div class="input-group input-group-sm mb-0">
<input type="file" class="form-control" id="inputGroupFile02">
<label class="input-group-text" for="inputGroupFile02">kB</label>
<input
type="file"
class="form-control"
id="inputGroupFile02"
/>
<label class="input-group-text" for="inputGroupFile02"
>kB</label
>
</div>
</div>
</div>
@ -35,19 +44,46 @@
<div class="row mb-2">
<div class="col-auto">
<div class="input-group input-group-sm">
<input type="text" class="form-control" style="max-width: 6rem" placeholder="DX Call" id="dxCall" maxlength="6" aria-label="Input group example" aria-describedby="btnGroupAddon">
<button type="button" id="sendPing"class="btn btn-primary">Ping</button>
<span class="input-group-text" id="tnc_running_state">ACK</span>
<span class="input-group-text" id="tnc_running_state">0000 km</span>
<span class="input-group-text" id="tnc_running_state">0 dB</span>
<input
type="text"
class="form-control"
style="max-width: 6rem"
placeholder="DX Call"
id="dxCall"
maxlength="6"
aria-label="Input group example"
aria-describedby="btnGroupAddon"
/>
<button
type="button"
id="sendPing"
class="btn btn-primary"
>
Ping
</button>
<span class="input-group-text" id="tnc_running_state"
>ACK</span
>
<span class="input-group-text" id="tnc_running_state"
>0000 km</span
>
<span class="input-group-text" id="tnc_running_state"
>0 dB</span
>
</div>
</div>
</div>
<div class="row">
<div class="col-auto">
<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 example" id="hamlib_deviceport">
<span class="input-group-text" id="basic-addon1"
>Mode</span
>
<select
class="form-select form-select-sm"
aria-label=".form-select-sm example"
id="hamlib_deviceport"
>
<option selected value="DATAC1">DATAC1</option>
<option value="DATAC3">DATAC3</option>
</select>
@ -55,8 +91,14 @@
</div>
<div class="col-auto">
<div class="input-group input-group-sm">
<span class="input-group-text" id="basic-addon1">Frames</span>
<select class="form-select form-select-sm" aria-label=".form-select-sm example" id="hamlib_deviceport">
<span class="input-group-text" id="basic-addon1"
>Frames</span
>
<select
class="form-select form-select-sm"
aria-label=".form-select-sm example"
id="hamlib_deviceport"
>
<option selected value="1">1</option>
<option value="2">2</option>
</select>
@ -64,7 +106,13 @@
</div>
<div class="col">
<div class="input-group input-group-sm">
<button type="button" id="startTransmission"class="btn btn-success">Send</button>
<button
type="button"
id="startTransmission"
class="btn btn-success"
>
Send
</button>
<!--<button type="button" id="stopTNC"class="btn btn-danger">STOP</button>-->
</div>
</div>
@ -79,15 +127,13 @@
<div class="col">
<div class="card text-dark bg-light mb-0">
<div class="card-header">Info</div>
<div class="card-body">
123
</div>
<div class="card-body">123</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<hr>
<hr />
</div>
</div>
<!--row-->
@ -97,41 +143,120 @@
<!---------------------------------------------------------------------- FOOTER AREA ------------------------------------------------------------>
<nav class="navbar fixed-bottom navbar-light bg-light">
<div class="container-fluid">
<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
<div class="btn-group btn-group-sm me-2" role="group" aria-label="First group">
<div
class="btn-toolbar"
role="toolbar"
aria-label="Toolbar with button groups"
>
<div
class="btn-group btn-group-sm me-2"
role="group"
aria-label="First group"
>
<button class="btn btn-secondary" id="ptt_state" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-broadcast-pin" viewBox="0 0 16 16">
<path d="M3.05 3.05a7 7 0 0 0 0 9.9.5.5 0 0 1-.707.707 8 8 0 0 1 0-11.314.5.5 0 0 1 .707.707zm2.122 2.122a4 4 0 0 0 0 5.656.5.5 0 1 1-.708.708 5 5 0 0 1 0-7.072.5.5 0 0 1 .708.708zm5.656-.708a.5.5 0 0 1 .708 0 5 5 0 0 1 0 7.072.5.5 0 1 1-.708-.708 4 4 0 0 0 0-5.656.5.5 0 0 1 0-.708zm2.122-2.12a.5.5 0 0 1 .707 0 8 8 0 0 1 0 11.313.5.5 0 0 1-.707-.707 7 7 0 0 0 0-9.9.5.5 0 0 1 0-.707zM6 8a2 2 0 1 1 2.5 1.937V15.5a.5.5 0 0 1-1 0V9.937A2 2 0 0 1 6 8z"/>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-broadcast-pin"
viewBox="0 0 16 16"
>
<path
d="M3.05 3.05a7 7 0 0 0 0 9.9.5.5 0 0 1-.707.707 8 8 0 0 1 0-11.314.5.5 0 0 1 .707.707zm2.122 2.122a4 4 0 0 0 0 5.656.5.5 0 1 1-.708.708 5 5 0 0 1 0-7.072.5.5 0 0 1 .708.708zm5.656-.708a.5.5 0 0 1 .708 0 5 5 0 0 1 0 7.072.5.5 0 1 1-.708-.708 4 4 0 0 0 0-5.656.5.5 0 0 1 0-.708zm2.122-2.12a.5.5 0 0 1 .707 0 8 8 0 0 1 0 11.313.5.5 0 0 1-.707-.707 7 7 0 0 0 0-9.9.5.5 0 0 1 0-.707zM6 8a2 2 0 1 1 2.5 1.937V15.5a.5.5 0 0 1-1 0V9.937A2 2 0 0 1 6 8z"
/>
</svg>
</button>
</div>
<div class="btn-group btn-group-sm me-2" role="group" aria-label="Second group">
<div
class="btn-group btn-group-sm me-2"
role="group"
aria-label="Second group"
>
<button class="btn btn-secondary" id="busy_state" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cpu" viewBox="0 0 16 16">
<path d="M5 0a.5.5 0 0 1 .5.5V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2A2.5 2.5 0 0 1 14 4.5h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14a2.5 2.5 0 0 1-2.5 2.5v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14A2.5 2.5 0 0 1 2 11.5H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2A2.5 2.5 0 0 1 4.5 2V.5A.5.5 0 0 1 5 0zm-.5 3A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 11.5 3h-7zM5 6.5A1.5 1.5 0 0 1 6.5 5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3zM6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"/>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-cpu"
viewBox="0 0 16 16"
>
<path
d="M5 0a.5.5 0 0 1 .5.5V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2A2.5 2.5 0 0 1 14 4.5h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14a2.5 2.5 0 0 1-2.5 2.5v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14A2.5 2.5 0 0 1 2 11.5H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2A2.5 2.5 0 0 1 4.5 2V.5A.5.5 0 0 1 5 0zm-.5 3A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 11.5 3h-7zM5 6.5A1.5 1.5 0 0 1 6.5 5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3zM6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"
/>
</svg>
</button>
</div>
<div class="btn-group btn-group-sm me-2" role="group" aria-label="Second group">
<div
class="btn-group btn-group-sm me-2"
role="group"
aria-label="Second group"
>
<button class="btn btn-secondary" id="arq_state" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left-right" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 11.5a.5.5 0 0 0 .5.5h11.793l-3.147 3.146a.5.5 0 0 0 .708.708l4-4a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 11H1.5a.5.5 0 0 0-.5.5zm14-7a.5.5 0 0 1-.5.5H2.707l3.147 3.146a.5.5 0 1 1-.708.708l-4-4a.5.5 0 0 1 0-.708l4-4a.5.5 0 1 1 .708.708L2.707 4H14.5a.5.5 0 0 1 .5.5z"/>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-arrow-left-right"
viewBox="0 0 16 16"
>
<path
fill-rule="evenodd"
d="M1 11.5a.5.5 0 0 0 .5.5h11.793l-3.147 3.146a.5.5 0 0 0 .708.708l4-4a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 11H1.5a.5.5 0 0 0-.5.5zm14-7a.5.5 0 0 1-.5.5H2.707l3.147 3.146a.5.5 0 1 1-.708.708l-4-4a.5.5 0 0 1 0-.708l4-4a.5.5 0 1 1 .708.708L2.707 4H14.5a.5.5 0 0 1 .5.5z"
/>
</svg>
</button>
</div>
<div class="btn-group btn-group-sm me-2 " role="group" aria-label="Third group">
<button class="btn btn-secondary" id="signalling_state" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-journal-code" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8.646 5.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 8 8.646 6.354a.5.5 0 0 1 0-.708zm-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 8l1.647-1.646a.5.5 0 0 0 0-.708z"/>
<path d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z"/>
<path d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z"/>
<div
class="btn-group btn-group-sm me-2"
role="group"
aria-label="Third group"
>
<button
class="btn btn-secondary"
id="signalling_state"
type="button"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-journal-code"
viewBox="0 0 16 16"
>
<path
fill-rule="evenodd"
d="M8.646 5.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 8 8.646 6.354a.5.5 0 0 1 0-.708zm-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 8l1.647-1.646a.5.5 0 0 0 0-.708z"
/>
<path
d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z"
/>
<path
d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z"
/>
</svg>
</button>
<button class="btn btn-secondary" id="data_state" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-journal-richtext" viewBox="0 0 16 16">
<path d="M7.5 3.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm-.861 1.542 1.33.886 1.854-1.855a.25.25 0 0 1 .289-.047L11 4.75V7a.5.5 0 0 1-.5.5h-5A.5.5 0 0 1 5 7v-.5s1.54-1.274 1.639-1.208zM5 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/>
<path d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z"/>
<path d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z"/>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-journal-richtext"
viewBox="0 0 16 16"
>
<path
d="M7.5 3.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm-.861 1.542 1.33.886 1.854-1.855a.25.25 0 0 1 .289-.047L11 4.75V7a.5.5 0 0 1-.5.5h-5A.5.5 0 0 1 5 7v-.5s1.54-1.274 1.639-1.208zM5 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"
/>
<path
d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z"
/>
<path
d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z"
/>
</svg>
</button>
</div>
@ -140,7 +265,17 @@
<span class="input-group-text" id="basic-addon1">----</span>
</div>
<div class="progress" style="height: 100%; width: 200px">
<div class="progress-bar progress-bar-striped bg-primary" id="arq-progress" role="progressbar" style="width: 25%" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">25%</div>
<div
class="progress-bar progress-bar-striped bg-primary"
id="arq-progress"
role="progressbar"
style="width: 25%"
aria-valuenow="25"
aria-valuemin="0"
aria-valuemax="100"
>
25%
</div>
</div>
</div>
</div>

File diff suppressed because it is too large Load Diff

View File

@ -1,43 +1,69 @@
<!doctype html>
<!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';">
<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">
<link
rel="stylesheet"
href="../node_modules/bootstrap/dist/css/bootstrap.min.css"
/>
<link rel="stylesheet" type="text/css" href="styles.css" />
<title>FreeDATA - Live Log</title>
</head>
<body>
<!-- bootstrap -->
<script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<!-- chart.js -->
<nav class="navbar fixed-top bg-light">
<div class="container-fluid">
<input type="checkbox" class="btn-check" id="enable_filter_info" autocomplete="off" checked>
<label class="btn btn-outline-info" for="enable_filter_info">info</label>
<input
type="checkbox"
class="btn-check"
id="enable_filter_info"
autocomplete="off"
checked
/>
<label class="btn btn-outline-info" for="enable_filter_info"
>info</label
>
<input type="checkbox" class="btn-check" id="enable_filter_debug" autocomplete="off">
<label class="btn btn-outline-primary" for="enable_filter_debug">debug</label>
<input
type="checkbox"
class="btn-check"
id="enable_filter_debug"
autocomplete="off"
/>
<label class="btn btn-outline-primary" for="enable_filter_debug"
>debug</label
>
<input type="checkbox" class="btn-check" id="enable_filter_warning" autocomplete="off">
<label class="btn btn-outline-warning" for="enable_filter_warning">warning</label>
<input type="checkbox" class="btn-check" id="enable_filter_error" autocomplete="off">
<label class="btn btn-outline-danger" for="enable_filter_error">error</label>
<input
type="checkbox"
class="btn-check"
id="enable_filter_warning"
autocomplete="off"
/>
<label class="btn btn-outline-warning" for="enable_filter_warning"
>warning</label
>
<input
type="checkbox"
class="btn-check"
id="enable_filter_error"
autocomplete="off"
/>
<label class="btn btn-outline-danger" for="enable_filter_error"
>error</label
>
</div>
</nav>
<div class="container-fluid mt-5">
<div class="tableFixHead">
<table class="table table-hover">

View File

@ -1,11 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Security-Policy" content="script-src 'self';">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="Content-Security-Policy" content="script-src 'self';" />
</head>
<body style="overflow:hidden;">
<img src="img/icon_cube_border.png" width="100%" height="100%">
<body style="overflow: hidden">
<img src="img/icon_cube_border.png" width="100%" height="100%" />
</body>
</html>

View File

@ -3,7 +3,6 @@ body {
padding-right: 0px !important;
overflow-y: hidden !important;
overflow-x: hidden !important;
}
/*Progress bars with centered text*/
@ -53,7 +52,8 @@ table {
border-collapse: collapse;
width: 100%;
}
th, td {
th,
td {
padding: 8px 16px;
}
@ -61,11 +61,9 @@ th {
background: #eee;
}
/* ------ emoji picker customization --------- */
.picker {
border-radius: 10px;
}
/* force gpu usage

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="author" content="Jeppe Ledet-Pedersen">
<meta charset="utf-8" />
<meta name="author" content="Jeppe Ledet-Pedersen" />
<title>Spectrum Plot</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>

View File

@ -1,4 +1,4 @@
'use strict';
"use strict";
/*
function connectWebSocket(spectrum) {
// var ws = new WebSocket("ws://" + window.location.host + "/websocket");
@ -35,15 +35,13 @@ function connectWebSocket(spectrum) {
function main() {
// Create spectrum object on canvas with ID "waterfall"
var spectrum = new Spectrum(
"waterfall", {
spectrumPercent: 20
var spectrum = new Spectrum("waterfall", {
spectrumPercent: 20,
});
// Connect to websocket
//connectWebSocket(spectrum);
//spectrum.setCenterHz("2000");
//spectrum.setSpanHz("1");
@ -55,7 +53,6 @@ for (var i = 0; i < 1000; i++) {
}
*/
// Bind keypress handler
window.addEventListener("keydown", function (e) {
spectrum.onKeypress(e);

View File

@ -37,12 +37,10 @@
var Waterfall, Rasterscan;
(function () {
Waterfall = function(ipBufAry, w, h, dir, options)
{
var direction = (typeof(dir) === "string")? dir.toLowerCase() : "down";
Waterfall = function (ipBufAry, w, h, dir, options) {
var direction = typeof dir === "string" ? dir.toLowerCase() : "down";
switch (direction)
{
switch (direction) {
case "up":
return new Spectrogram(ipBufAry, w, h, "WF", false, true, options);
case "down":
@ -53,14 +51,12 @@ var Waterfall, Rasterscan;
case "right":
return new Spectrogram(ipBufAry, w, h, "WF", true, false, options);
}
}
};
Rasterscan = function(ipBufAry, w, h, dir, options)
{
const direction = (typeof(dir) === "string")? dir.toLowerCase() : "down";
Rasterscan = function (ipBufAry, w, h, dir, options) {
const direction = typeof dir === "string" ? dir.toLowerCase() : "down";
switch (direction)
{
switch (direction) {
case "up":
return new Spectrogram(ipBufAry, w, h, "RS", true, true, options);
case "down":
@ -71,11 +67,10 @@ var Waterfall, Rasterscan;
case "right":
return new Spectrogram(ipBufAry, w, h, "RS", true, false, options);
}
}
};
function Spectrogram(ipBufAry, w, h, sgMode, rhc, vert, options)
{
const opt = (typeof options === 'object')? options: {}; // avoid undeclared object errors
function Spectrogram(ipBufAry, w, h, sgMode, rhc, vert, options) {
const opt = typeof options === "object" ? options : {}; // avoid undeclared object errors
let offScreenCtx; // offscreen canvas drawing context
const pxPerLine = w || 200;
const lines = h || 200;
@ -100,94 +95,282 @@ var Waterfall, Rasterscan;
let sgStartTime = 0;
// Matlab Jet ref: stackoverflow.com grayscale-to-red-green-blue-matlab-jet-color-scale
let colMap = [[ 0, 0, 128, 255], [ 0, 0, 131, 255], [ 0, 0, 135, 255], [ 0, 0, 139, 255],
[ 0, 0, 143, 255], [ 0, 0, 147, 255], [ 0, 0, 151, 255], [ 0, 0, 155, 255],
[ 0, 0, 159, 255], [ 0, 0, 163, 255], [ 0, 0, 167, 255], [ 0, 0, 171, 255],
[ 0, 0, 175, 255], [ 0, 0, 179, 255], [ 0, 0, 183, 255], [ 0, 0, 187, 255],
[ 0, 0, 191, 255], [ 0, 0, 195, 255], [ 0, 0, 199, 255], [ 0, 0, 203, 255],
[ 0, 0, 207, 255], [ 0, 0, 211, 255], [ 0, 0, 215, 255], [ 0, 0, 219, 255],
[ 0, 0, 223, 255], [ 0, 0, 227, 255], [ 0, 0, 231, 255], [ 0, 0, 235, 255],
[ 0, 0, 239, 255], [ 0, 0, 243, 255], [ 0, 0, 247, 255], [ 0, 0, 251, 255],
[ 0, 0, 255, 255], [ 0, 4, 255, 255], [ 0, 8, 255, 255], [ 0, 12, 255, 255],
[ 0, 16, 255, 255], [ 0, 20, 255, 255], [ 0, 24, 255, 255], [ 0, 28, 255, 255],
[ 0, 32, 255, 255], [ 0, 36, 255, 255], [ 0, 40, 255, 255], [ 0, 44, 255, 255],
[ 0, 48, 255, 255], [ 0, 52, 255, 255], [ 0, 56, 255, 255], [ 0, 60, 255, 255],
[ 0, 64, 255, 255], [ 0, 68, 255, 255], [ 0, 72, 255, 255], [ 0, 76, 255, 255],
[ 0, 80, 255, 255], [ 0, 84, 255, 255], [ 0, 88, 255, 255], [ 0, 92, 255, 255],
[ 0, 96, 255, 255], [ 0, 100, 255, 255], [ 0, 104, 255, 255], [ 0, 108, 255, 255],
[ 0, 112, 255, 255], [ 0, 116, 255, 255], [ 0, 120, 255, 255], [ 0, 124, 255, 255],
[ 0, 128, 255, 255], [ 0, 131, 255, 255], [ 0, 135, 255, 255], [ 0, 139, 255, 255],
[ 0, 143, 255, 255], [ 0, 147, 255, 255], [ 0, 151, 255, 255], [ 0, 155, 255, 255],
[ 0, 159, 255, 255], [ 0, 163, 255, 255], [ 0, 167, 255, 255], [ 0, 171, 255, 255],
[ 0, 175, 255, 255], [ 0, 179, 255, 255], [ 0, 183, 255, 255], [ 0, 187, 255, 255],
[ 0, 191, 255, 255], [ 0, 195, 255, 255], [ 0, 199, 255, 255], [ 0, 203, 255, 255],
[ 0, 207, 255, 255], [ 0, 211, 255, 255], [ 0, 215, 255, 255], [ 0, 219, 255, 255],
[ 0, 223, 255, 255], [ 0, 227, 255, 255], [ 0, 231, 255, 255], [ 0, 235, 255, 255],
[ 0, 239, 255, 255], [ 0, 243, 255, 255], [ 0, 247, 255, 255], [ 0, 251, 255, 255],
[ 0, 255, 255, 255], [ 4, 255, 251, 255], [ 8, 255, 247, 255], [ 12, 255, 243, 255],
[ 16, 255, 239, 255], [ 20, 255, 235, 255], [ 24, 255, 231, 255], [ 28, 255, 227, 255],
[ 32, 255, 223, 255], [ 36, 255, 219, 255], [ 40, 255, 215, 255], [ 44, 255, 211, 255],
[ 48, 255, 207, 255], [ 52, 255, 203, 255], [ 56, 255, 199, 255], [ 60, 255, 195, 255],
[ 64, 255, 191, 255], [ 68, 255, 187, 255], [ 72, 255, 183, 255], [ 76, 255, 179, 255],
[ 80, 255, 175, 255], [ 84, 255, 171, 255], [ 88, 255, 167, 255], [ 92, 255, 163, 255],
[ 96, 255, 159, 255], [100, 255, 155, 255], [104, 255, 151, 255], [108, 255, 147, 255],
[112, 255, 143, 255], [116, 255, 139, 255], [120, 255, 135, 255], [124, 255, 131, 255],
[128, 255, 128, 255], [131, 255, 124, 255], [135, 255, 120, 255], [139, 255, 116, 255],
[143, 255, 112, 255], [147, 255, 108, 255], [151, 255, 104, 255], [155, 255, 100, 255],
[159, 255, 96, 255], [163, 255, 92, 255], [167, 255, 88, 255], [171, 255, 84, 255],
[175, 255, 80, 255], [179, 255, 76, 255], [183, 255, 72, 255], [187, 255, 68, 255],
[191, 255, 64, 255], [195, 255, 60, 255], [199, 255, 56, 255], [203, 255, 52, 255],
[207, 255, 48, 255], [211, 255, 44, 255], [215, 255, 40, 255], [219, 255, 36, 255],
[223, 255, 32, 255], [227, 255, 28, 255], [231, 255, 24, 255], [235, 255, 20, 255],
[239, 255, 16, 255], [243, 255, 12, 255], [247, 255, 8, 255], [251, 255, 4, 255],
[255, 255, 0, 255], [255, 251, 0, 255], [255, 247, 0, 255], [255, 243, 0, 255],
[255, 239, 0, 255], [255, 235, 0, 255], [255, 231, 0, 255], [255, 227, 0, 255],
[255, 223, 0, 255], [255, 219, 0, 255], [255, 215, 0, 255], [255, 211, 0, 255],
[255, 207, 0, 255], [255, 203, 0, 255], [255, 199, 0, 255], [255, 195, 0, 255],
[255, 191, 0, 255], [255, 187, 0, 255], [255, 183, 0, 255], [255, 179, 0, 255],
[255, 175, 0, 255], [255, 171, 0, 255], [255, 167, 0, 255], [255, 163, 0, 255],
[255, 159, 0, 255], [255, 155, 0, 255], [255, 151, 0, 255], [255, 147, 0, 255],
[255, 143, 0, 255], [255, 139, 0, 255], [255, 135, 0, 255], [255, 131, 0, 255],
[255, 128, 0, 255], [255, 124, 0, 255], [255, 120, 0, 255], [255, 116, 0, 255],
[255, 112, 0, 255], [255, 108, 0, 255], [255, 104, 0, 255], [255, 100, 0, 255],
[255, 96, 0, 255], [255, 92, 0, 255], [255, 88, 0, 255], [255, 84, 0, 255],
[255, 80, 0, 255], [255, 76, 0, 255], [255, 72, 0, 255], [255, 68, 0, 255],
[255, 64, 0, 255], [255, 60, 0, 255], [255, 56, 0, 255], [255, 52, 0, 255],
[255, 48, 0, 255], [255, 44, 0, 255], [255, 40, 0, 255], [255, 36, 0, 255],
[255, 32, 0, 255], [255, 28, 0, 255], [255, 24, 0, 255], [255, 20, 0, 255],
[255, 16, 0, 255], [255, 12, 0, 255], [255, 8, 0, 255], [255, 4, 0, 255],
[255, 0, 0, 255], [251, 0, 0, 255], [247, 0, 0, 255], [243, 0, 0, 255],
[239, 0, 0, 255], [235, 0, 0, 255], [231, 0, 0, 255], [227, 0, 0, 255],
[223, 0, 0, 255], [219, 0, 0, 255], [215, 0, 0, 255], [211, 0, 0, 255],
[207, 0, 0, 255], [203, 0, 0, 255], [199, 0, 0, 255], [195, 0, 0, 255],
[191, 0, 0, 255], [187, 0, 0, 255], [183, 0, 0, 255], [179, 0, 0, 255],
[175, 0, 0, 255], [171, 0, 0, 255], [167, 0, 0, 255], [163, 0, 0, 255],
[159, 0, 0, 255], [155, 0, 0, 255], [151, 0, 0, 255], [147, 0, 0, 255],
[143, 0, 0, 255], [139, 0, 0, 255], [135, 0, 0, 255], [131, 0, 0, 255],
[ 0, 0, 0, 0]];
let colMap = [
[0, 0, 128, 255],
[0, 0, 131, 255],
[0, 0, 135, 255],
[0, 0, 139, 255],
[0, 0, 143, 255],
[0, 0, 147, 255],
[0, 0, 151, 255],
[0, 0, 155, 255],
[0, 0, 159, 255],
[0, 0, 163, 255],
[0, 0, 167, 255],
[0, 0, 171, 255],
[0, 0, 175, 255],
[0, 0, 179, 255],
[0, 0, 183, 255],
[0, 0, 187, 255],
[0, 0, 191, 255],
[0, 0, 195, 255],
[0, 0, 199, 255],
[0, 0, 203, 255],
[0, 0, 207, 255],
[0, 0, 211, 255],
[0, 0, 215, 255],
[0, 0, 219, 255],
[0, 0, 223, 255],
[0, 0, 227, 255],
[0, 0, 231, 255],
[0, 0, 235, 255],
[0, 0, 239, 255],
[0, 0, 243, 255],
[0, 0, 247, 255],
[0, 0, 251, 255],
[0, 0, 255, 255],
[0, 4, 255, 255],
[0, 8, 255, 255],
[0, 12, 255, 255],
[0, 16, 255, 255],
[0, 20, 255, 255],
[0, 24, 255, 255],
[0, 28, 255, 255],
[0, 32, 255, 255],
[0, 36, 255, 255],
[0, 40, 255, 255],
[0, 44, 255, 255],
[0, 48, 255, 255],
[0, 52, 255, 255],
[0, 56, 255, 255],
[0, 60, 255, 255],
[0, 64, 255, 255],
[0, 68, 255, 255],
[0, 72, 255, 255],
[0, 76, 255, 255],
[0, 80, 255, 255],
[0, 84, 255, 255],
[0, 88, 255, 255],
[0, 92, 255, 255],
[0, 96, 255, 255],
[0, 100, 255, 255],
[0, 104, 255, 255],
[0, 108, 255, 255],
[0, 112, 255, 255],
[0, 116, 255, 255],
[0, 120, 255, 255],
[0, 124, 255, 255],
[0, 128, 255, 255],
[0, 131, 255, 255],
[0, 135, 255, 255],
[0, 139, 255, 255],
[0, 143, 255, 255],
[0, 147, 255, 255],
[0, 151, 255, 255],
[0, 155, 255, 255],
[0, 159, 255, 255],
[0, 163, 255, 255],
[0, 167, 255, 255],
[0, 171, 255, 255],
[0, 175, 255, 255],
[0, 179, 255, 255],
[0, 183, 255, 255],
[0, 187, 255, 255],
[0, 191, 255, 255],
[0, 195, 255, 255],
[0, 199, 255, 255],
[0, 203, 255, 255],
[0, 207, 255, 255],
[0, 211, 255, 255],
[0, 215, 255, 255],
[0, 219, 255, 255],
[0, 223, 255, 255],
[0, 227, 255, 255],
[0, 231, 255, 255],
[0, 235, 255, 255],
[0, 239, 255, 255],
[0, 243, 255, 255],
[0, 247, 255, 255],
[0, 251, 255, 255],
[0, 255, 255, 255],
[4, 255, 251, 255],
[8, 255, 247, 255],
[12, 255, 243, 255],
[16, 255, 239, 255],
[20, 255, 235, 255],
[24, 255, 231, 255],
[28, 255, 227, 255],
[32, 255, 223, 255],
[36, 255, 219, 255],
[40, 255, 215, 255],
[44, 255, 211, 255],
[48, 255, 207, 255],
[52, 255, 203, 255],
[56, 255, 199, 255],
[60, 255, 195, 255],
[64, 255, 191, 255],
[68, 255, 187, 255],
[72, 255, 183, 255],
[76, 255, 179, 255],
[80, 255, 175, 255],
[84, 255, 171, 255],
[88, 255, 167, 255],
[92, 255, 163, 255],
[96, 255, 159, 255],
[100, 255, 155, 255],
[104, 255, 151, 255],
[108, 255, 147, 255],
[112, 255, 143, 255],
[116, 255, 139, 255],
[120, 255, 135, 255],
[124, 255, 131, 255],
[128, 255, 128, 255],
[131, 255, 124, 255],
[135, 255, 120, 255],
[139, 255, 116, 255],
[143, 255, 112, 255],
[147, 255, 108, 255],
[151, 255, 104, 255],
[155, 255, 100, 255],
[159, 255, 96, 255],
[163, 255, 92, 255],
[167, 255, 88, 255],
[171, 255, 84, 255],
[175, 255, 80, 255],
[179, 255, 76, 255],
[183, 255, 72, 255],
[187, 255, 68, 255],
[191, 255, 64, 255],
[195, 255, 60, 255],
[199, 255, 56, 255],
[203, 255, 52, 255],
[207, 255, 48, 255],
[211, 255, 44, 255],
[215, 255, 40, 255],
[219, 255, 36, 255],
[223, 255, 32, 255],
[227, 255, 28, 255],
[231, 255, 24, 255],
[235, 255, 20, 255],
[239, 255, 16, 255],
[243, 255, 12, 255],
[247, 255, 8, 255],
[251, 255, 4, 255],
[255, 255, 0, 255],
[255, 251, 0, 255],
[255, 247, 0, 255],
[255, 243, 0, 255],
[255, 239, 0, 255],
[255, 235, 0, 255],
[255, 231, 0, 255],
[255, 227, 0, 255],
[255, 223, 0, 255],
[255, 219, 0, 255],
[255, 215, 0, 255],
[255, 211, 0, 255],
[255, 207, 0, 255],
[255, 203, 0, 255],
[255, 199, 0, 255],
[255, 195, 0, 255],
[255, 191, 0, 255],
[255, 187, 0, 255],
[255, 183, 0, 255],
[255, 179, 0, 255],
[255, 175, 0, 255],
[255, 171, 0, 255],
[255, 167, 0, 255],
[255, 163, 0, 255],
[255, 159, 0, 255],
[255, 155, 0, 255],
[255, 151, 0, 255],
[255, 147, 0, 255],
[255, 143, 0, 255],
[255, 139, 0, 255],
[255, 135, 0, 255],
[255, 131, 0, 255],
[255, 128, 0, 255],
[255, 124, 0, 255],
[255, 120, 0, 255],
[255, 116, 0, 255],
[255, 112, 0, 255],
[255, 108, 0, 255],
[255, 104, 0, 255],
[255, 100, 0, 255],
[255, 96, 0, 255],
[255, 92, 0, 255],
[255, 88, 0, 255],
[255, 84, 0, 255],
[255, 80, 0, 255],
[255, 76, 0, 255],
[255, 72, 0, 255],
[255, 68, 0, 255],
[255, 64, 0, 255],
[255, 60, 0, 255],
[255, 56, 0, 255],
[255, 52, 0, 255],
[255, 48, 0, 255],
[255, 44, 0, 255],
[255, 40, 0, 255],
[255, 36, 0, 255],
[255, 32, 0, 255],
[255, 28, 0, 255],
[255, 24, 0, 255],
[255, 20, 0, 255],
[255, 16, 0, 255],
[255, 12, 0, 255],
[255, 8, 0, 255],
[255, 4, 0, 255],
[255, 0, 0, 255],
[251, 0, 0, 255],
[247, 0, 0, 255],
[243, 0, 0, 255],
[239, 0, 0, 255],
[235, 0, 0, 255],
[231, 0, 0, 255],
[227, 0, 0, 255],
[223, 0, 0, 255],
[219, 0, 0, 255],
[215, 0, 0, 255],
[211, 0, 0, 255],
[207, 0, 0, 255],
[203, 0, 0, 255],
[199, 0, 0, 255],
[195, 0, 0, 255],
[191, 0, 0, 255],
[187, 0, 0, 255],
[183, 0, 0, 255],
[179, 0, 0, 255],
[175, 0, 0, 255],
[171, 0, 0, 255],
[167, 0, 0, 255],
[163, 0, 0, 255],
[159, 0, 0, 255],
[155, 0, 0, 255],
[151, 0, 0, 255],
[147, 0, 0, 255],
[143, 0, 0, 255],
[139, 0, 0, 255],
[135, 0, 0, 255],
[131, 0, 0, 255],
[0, 0, 0, 0],
];
function incrLine()
{
if ((vert && !rhc) || (!vert && rhc))
{
function incrLine() {
if ((vert && !rhc) || (!vert && rhc)) {
nextLine++;
if (nextLine >= lines)
{
if (nextLine >= lines) {
nextLine = 0;
}
}
else
{
} else {
nextLine--;
if (nextLine < 0)
{
if (nextLine < 0) {
nextLine = lines - 1;
}
}
}
function updateWaterfall() // update dynamic waterfalls at a fixed rate
{
function updateWaterfall() {
// update dynamic waterfalls at a fixed rate
let sgDiff;
// grab latest line of data, write it to off screen buffer, inc 'nextLine'
@ -195,26 +378,20 @@ var Waterfall, Rasterscan;
// loop to write data data at the desired rate, data is being updated asynchronously
// ref for accurate timeout: http://www.sitepoint.com/creating-accurate-timers-in-javascript
sgTime += interval;
sgDiff = (Date.now() - sgStartTime) - sgTime;
if (running)
{
sgDiff = Date.now() - sgStartTime - sgTime;
if (running) {
timerID = setTimeout(updateWaterfall, interval - sgDiff);
}
}
function sgSetLineRate(newRate)
{
if (isNaN(newRate) || newRate > 50 || newRate < 0)
{
function sgSetLineRate(newRate) {
if (isNaN(newRate) || newRate > 50 || newRate < 0) {
console.error("invalid line rate [0 <= lineRate < 50 lines/sec]");
// don't change the lineRate;
}
else if (newRate === 0) // static (one pass) raster
{
} else if (newRate === 0) {
// static (one pass) raster
lineRate = 0;
}
else
{
} else {
lineRate = newRate;
interval = 1000 / lineRate; // msec
}
@ -222,37 +399,35 @@ var Waterfall, Rasterscan;
this.setLineRate = sgSetLineRate;
function setProperty(propertyName, value)
{
if ((typeof propertyName !== "string")||(value === undefined)) // null is OK, forces default
{
function setProperty(propertyName, value) {
if (typeof propertyName !== "string" || value === undefined) {
// null is OK, forces default
return;
}
switch (propertyName.toLowerCase())
{
switch (propertyName.toLowerCase()) {
case "linerate":
sgSetLineRate(value); // setLine does checks for number etc
break;
case "startbin":
if (!isNaN(value) && value > 0)
{
if (!isNaN(value) && value > 0) {
startOfs = value;
}
break;
case "onscreenparentid":
if (typeof value === "string" && document.getElementById(value))
{
if (typeof value === "string" && document.getElementById(value)) {
demoCvsId = value;
}
break;
case "colormap":
if (Array.isArray(value) && Array.isArray(value[0]) && value[0].length == 4)
{
if (
Array.isArray(value) &&
Array.isArray(value[0]) &&
value[0].length == 4
) {
colMap = value; // value must be an array of 4 element arrays to get here
if (colMap.length<256) // fill out the remaining colors with last color
{
for (let i=colMap.length; i<256; i++)
{
if (colMap.length < 256) {
// fill out the remaining colors with last color
for (let i = colMap.length; i < 256; i++) {
colMap[i] = colMap[colMap.length - 1];
}
}
@ -263,28 +438,26 @@ var Waterfall, Rasterscan;
}
}
function verticalNewLine()
{
function verticalNewLine() {
let tmpImgData, ipBuf8;
if (sgMode == "WF")
{
if (rhc)
{
if (sgMode == "WF") {
if (rhc) {
// shift the current display down 1 line, oldest line drops off
tmpImgData = offScreenCtx.getImageData(0, 0, pxPerLine, lines - 1);
offScreenCtx.putImageData(tmpImgData, 0, 1);
}
else
{
} else {
// shift the current display up 1 line, oldest line drops off
tmpImgData = offScreenCtx.getImageData(0, 1, pxPerLine, lines - 1);
offScreenCtx.putImageData(tmpImgData, 0, 0);
}
}
ipBuf8 = Uint8ClampedArray.from(ipBufAry[0]);
for (let sigVal, rgba, opIdx = 0, ipIdx = startOfs; ipIdx < pxPerLine+startOfs; opIdx += 4, ipIdx++)
{
for (
let sigVal, rgba, opIdx = 0, ipIdx = startOfs;
ipIdx < pxPerLine + startOfs;
opIdx += 4, ipIdx++
) {
sigVal = ipBuf8[ipIdx] || 0; // if input line too short add zeros
rgba = colMap[sigVal]; // array of rgba values
// byte reverse so number aa bb gg rr
@ -294,31 +467,24 @@ var Waterfall, Rasterscan;
lineBuf8[opIdx + 3] = rgba[3]; // alpha
}
offScreenCtx.putImageData(lineImgData, 0, nextLine);
if (sgMode === "RS")
{
if (sgMode === "RS") {
incrLine();
// if not static draw a white line in front of the current line to indicate new data point
if (lineRate)
{
if (lineRate) {
offScreenCtx.putImageData(blankImgData, 0, nextLine);
}
}
};
}
function horizontalNewLine()
{
function horizontalNewLine() {
let tmpImgData, ipBuf8;
if (sgMode == "WF")
{
if (rhc)
{
if (sgMode == "WF") {
if (rhc) {
// shift the current display right 1 line, oldest line drops off
tmpImgData = offScreenCtx.getImageData(0, 0, lines - 1, pxPerLine);
offScreenCtx.putImageData(tmpImgData, 1, 0);
}
else
{
} else {
// shift the current display left 1 line, oldest line drops off
tmpImgData = offScreenCtx.getImageData(1, 0, lines - 1, pxPerLine);
offScreenCtx.putImageData(tmpImgData, 0, 0);
@ -326,17 +492,13 @@ var Waterfall, Rasterscan;
}
// refresh the page image (it was just shifted)
pageImgData = offScreenCtx.getImageData(0, 0, lines, pxPerLine);
if (ipBufAry[0].constructor !== Uint8Array)
{
if (ipBufAry[0].constructor !== Uint8Array) {
ipBuf8 = Uint8ClampedArray.from(ipBufAry[0]); // clamp input values to 0..255 range
}
else
{
} else {
ipBuf8 = ipBufAry[0]; // conversion already done
}
for (let sigVal, rgba, opIdx, ipIdx=0; ipIdx < pxPerLine; ipIdx++)
{
for (let sigVal, rgba, opIdx, ipIdx = 0; ipIdx < pxPerLine; ipIdx++) {
sigVal = ipBuf8[ipIdx + startOfs] || 0; // if input line too short add zeros
rgba = colMap[sigVal]; // array of rgba values
opIdx = 4 * ((pxPerLine - ipIdx - 1) * lines + nextLine);
@ -346,20 +508,14 @@ var Waterfall, Rasterscan;
pageImgData.data[opIdx + 2] = rgba[2]; // blue
pageImgData.data[opIdx + 3] = rgba[3]; // alpha
}
if (sgMode === "RS")
{
if (sgMode === "RS") {
incrLine();
// if not draw a white line in front of the current line to indicate new data point
if (lineRate)
{
for (let j=0; j < pxPerLine; j++)
{
if (rhc)
{
if (lineRate) {
for (let j = 0; j < pxPerLine; j++) {
if (rhc) {
opIdx = 4 * (j * lines + nextLine);
}
else
{
} else {
opIdx = 4 * ((pxPerLine - j - 1) * lines + nextLine);
}
// byte reverse so number aa bb gg rr
@ -371,16 +527,14 @@ var Waterfall, Rasterscan;
}
}
offScreenCtx.putImageData(pageImgData, 0, 0);
};
}
const sgNewLine = (vert)? verticalNewLine: horizontalNewLine; // function pointers
const sgNewLine = vert ? verticalNewLine : horizontalNewLine; // function pointers
//===== set all the options ================
for (let prop in opt)
{
for (let prop in opt) {
// check that this is opt's own property, not inherited from prototype
if (opt.hasOwnProperty(prop))
{
if (opt.hasOwnProperty(prop)) {
setProperty(prop, opt[prop]);
}
}
@ -389,63 +543,51 @@ var Waterfall, Rasterscan;
this.newLine = sgNewLine;
this.offScreenCvs = document.createElement("canvas");
if (vert)
{
this.offScreenCvs.setAttribute('width', pxPerLine); // reset canvas pixels width
this.offScreenCvs.setAttribute('height', lines); // don't use style for this
if (vert) {
this.offScreenCvs.setAttribute("width", pxPerLine); // reset canvas pixels width
this.offScreenCvs.setAttribute("height", lines); // don't use style for this
clearImgData = new ImageData(clearBuf8, pxPerLine, lines);
}
else // data written in columns
{
this.offScreenCvs.setAttribute('width', lines); // reset canvas pixels width
this.offScreenCvs.setAttribute('height', pxPerLine); // don't use style for this
} // data written in columns
else {
this.offScreenCvs.setAttribute("width", lines); // reset canvas pixels width
this.offScreenCvs.setAttribute("height", pxPerLine); // don't use style for this
clearImgData = new ImageData(clearBuf8, lines, pxPerLine);
}
offScreenCtx = this.offScreenCvs.getContext("2d");
this.clear = function()
{
this.clear = function () {
offScreenCtx.putImageData(clearImgData, 0, 0);
};
this.start = function()
{
this.start = function () {
sgStartTime = Date.now();
sgTime = 0;
running = true;
updateWaterfall(); // start the update loop
};
this.stop = function()
{
this.stop = function () {
running = false;
if (timerID)
{
if (timerID) {
clearTimeout(timerID);
}
// reset where the next line is to be written
if (sgMode === "RS")
{
if (vert)
{
nextLine = (rhc)? lines-1 : 0;
if (sgMode === "RS") {
if (vert) {
nextLine = rhc ? lines - 1 : 0;
} else {
nextLine = rhc ? 0 : lines - 1;
}
else
{
nextLine = (rhc)? 0 : lines-1;
}
}
else // WF
{
nextLine = (rhc)? 0 : lines-1;
} // WF
else {
nextLine = rhc ? 0 : lines - 1;
}
};
// make a white line, it will show the input line for RS displays
blankBuf8.fill(255);
// make a full canvas of the color map 0 values
for (let i=0; i<pxPerLine*lines*4; i+=4)
{
for (let i = 0; i < pxPerLine * lines * 4; i += 4) {
// byte reverse so number aa bb gg rr
clearBuf8[i] = colMap[0][0]; // red
clearBuf8[i + 1] = colMap[0][1]; // green
@ -453,8 +595,7 @@ var Waterfall, Rasterscan;
clearBuf8[i + 3] = colMap[0][3]; // alpha
}
// for diagnostics only
if (typeof(demoCvsId) == "string")
{
if (typeof demoCvsId == "string") {
document.getElementById(demoCvsId).appendChild(this.offScreenCvs);
}
// initialize the direction and first line position
@ -463,4 +604,4 @@ var Waterfall, Rasterscan;
// everything is set
// if dynamic, wait for the start or newLine methods to be called
}
}())
})();

View File

@ -4,16 +4,16 @@
* See the LICENSE file for further details.
*/
'use strict';
"use strict";
Spectrum.prototype.squeeze = function (value, out_min, out_max) {
if (value <= this.min_db)
return out_min;
else if (value >= this.max_db)
return out_max;
if (value <= this.min_db) return out_min;
else if (value >= this.max_db) return out_max;
else
return Math.round((value - this.min_db) / (this.max_db - this.min_db) * out_max);
}
return Math.round(
((value - this.min_db) / (this.max_db - this.min_db)) * out_max
);
};
Spectrum.prototype.rowToImageData = function (bins) {
for (var i = 0; i < this.imagedata.data.length; i += 4) {
@ -24,13 +24,21 @@ Spectrum.prototype.rowToImageData = function(bins) {
this.imagedata.data[i + 2] = color[2];
this.imagedata.data[i + 3] = 255;
}
}
};
Spectrum.prototype.addWaterfallRow = function (bins) {
// Shift waterfall 1 row down
this.ctx_wf.drawImage(this.ctx_wf.canvas,
0, 0, this.wf_size, this.wf_rows - 1,
0, 1, this.wf_size, this.wf_rows - 1);
this.ctx_wf.drawImage(
this.ctx_wf.canvas,
0,
0,
this.wf_size,
this.wf_rows - 1,
0,
1,
this.wf_size,
this.wf_rows - 1
);
// Draw new line on waterfall canvas
this.rowToImageData(bins);
@ -43,37 +51,40 @@ Spectrum.prototype.addWaterfallRow = function(bins) {
// fit in waterfall area to avoid vertical scaling.
this.ctx.imageSmoothingEnabled = false;
var rows = Math.min(this.wf_rows, height - this.spectrumHeight);
this.ctx.drawImage(this.ctx_wf.canvas,
0, 0, this.wf_size, rows,
0, this.spectrumHeight, width, height - this.spectrumHeight);
}
this.ctx.drawImage(
this.ctx_wf.canvas,
0,
0,
this.wf_size,
rows,
0,
this.spectrumHeight,
width,
height - this.spectrumHeight
);
};
Spectrum.prototype.drawFFT = function (bins) {
this.ctx.beginPath();
this.ctx.moveTo(-1, this.spectrumHeight + 1);
for (var i = 0; i < bins.length; i++) {
var y = this.spectrumHeight - this.squeeze(bins[i], 0, this.spectrumHeight);
if (y > this.spectrumHeight - 1)
y = this.spectrumHeight + 1; // Hide underflow
if (y < 0)
y = 0;
if (i == 0)
this.ctx.lineTo(-1, y);
if (y > this.spectrumHeight - 1) y = this.spectrumHeight + 1; // Hide underflow
if (y < 0) y = 0;
if (i == 0) this.ctx.lineTo(-1, y);
this.ctx.lineTo(i, y);
if (i == bins.length - 1)
this.ctx.lineTo(this.wf_size + 1, y);
if (i == bins.length - 1) this.ctx.lineTo(this.wf_size + 1, y);
}
this.ctx.lineTo(this.wf_size + 1, this.spectrumHeight + 1);
this.ctx.strokeStyle = "#fefefe";
this.ctx.stroke();
}
};
//Spectrum.prototype.drawSpectrum = function(bins) {
Spectrum.prototype.drawSpectrum = function () {
var width = this.ctx.canvas.width;
var height = this.ctx.canvas.height;
// Modification by DJ2LS
// Draw bandwidth lines
// TODO: Math not correct. But a first attempt
@ -104,12 +115,11 @@ Spectrum.prototype.drawFFT = function(bins) {
this.ctx_wf.moveTo(linePositionHigh2, 0);
this.ctx_wf.lineTo(linePositionHigh2, height);
this.ctx_wf.lineWidth = 1;
this.ctx_wf.strokeStyle = '#C3C3C3';
this.ctx_wf.stroke()
this.ctx_wf.strokeStyle = "#C3C3C3";
this.ctx_wf.stroke();
// ---- END OF MODIFICATION ------
// Fill with black
this.ctx.fillStyle = "white";
this.ctx.fillRect(0, 0, width, height);
@ -170,12 +180,12 @@ Spectrum.prototype.drawFFT = function(bins) {
// Copy axes from offscreen canvas
this.ctx.drawImage(this.ctx_axes.canvas, 0, 0);
*/
}
};
//Allow setting colormap
Spectrum.prototype.setColorMap = function (index) {
this.colormap = colormaps[index];
}
};
Spectrum.prototype.updateAxes = function () {
var width = this.ctx_axes.canvas.width;
@ -218,11 +228,9 @@ Spectrum.prototype.updateAxes = function() {
this.ctx_axes.textAlign = "center";
}
var freq = this.centerHz + this.spanHz / 10 * (i - 5);
if (this.centerHz + this.spanHz > 1e6)
freq = freq / 1e6 + "M";
else if (this.centerHz + this.spanHz > 1e3)
freq = freq / 1e3 + "k";
var freq = this.centerHz + (this.spanHz / 10) * (i - 5);
if (this.centerHz + this.spanHz > 1e6) freq = freq / 1e6 + "M";
else if (this.centerHz + this.spanHz > 1e3) freq = freq / 1e3 + "k";
this.ctx_axes.fillText(freq, x + adjust, height - 3);
}
@ -232,7 +240,7 @@ Spectrum.prototype.updateAxes = function() {
this.ctx_axes.strokeStyle = "rgba(200, 200, 200, 0.10)";
this.ctx_axes.stroke();
}
}
};
Spectrum.prototype.addData = function (data) {
if (!this.paused) {
@ -248,132 +256,132 @@ Spectrum.prototype.addData = function(data) {
this.addWaterfallRow(data);
this.resize();
}
}
};
Spectrum.prototype.updateSpectrumRatio = function () {
this.spectrumHeight = Math.round(this.canvas.height * this.spectrumPercent / 100.0);
this.spectrumHeight = Math.round(
(this.canvas.height * this.spectrumPercent) / 100.0
);
this.gradient = this.ctx.createLinearGradient(0, 0, 0, this.spectrumHeight);
for (var i = 0; i < this.colormap.length; i++) {
var c = this.colormap[this.colormap.length - 1 - i];
this.gradient.addColorStop(i / this.colormap.length,
"rgba(" + c[0] + "," + c[1] + "," + c[2] + ", 1.0)");
}
this.gradient.addColorStop(
i / this.colormap.length,
"rgba(" + c[0] + "," + c[1] + "," + c[2] + ", 1.0)"
);
}
};
Spectrum.prototype.resize = function () {
var width = this.canvas.clientWidth;
var height = this.canvas.clientHeight;
if (this.canvas.width != width ||
this.canvas.height != height) {
if (this.canvas.width != width || this.canvas.height != height) {
this.canvas.width = width;
this.canvas.height = height;
this.updateSpectrumRatio();
}
if (this.axes.width != width ||
this.axes.height != this.spectrumHeight) {
if (this.axes.width != width || this.axes.height != this.spectrumHeight) {
this.axes.width = width;
this.axes.height = this.spectrumHeight;
this.updateAxes();
}
}
};
Spectrum.prototype.setSpectrumPercent = function (percent) {
if (percent >= 0 && percent <= 100) {
this.spectrumPercent = percent;
this.updateSpectrumRatio();
}
}
};
Spectrum.prototype.incrementSpectrumPercent = function () {
if (this.spectrumPercent + this.spectrumPercentStep <= 100) {
this.setSpectrumPercent(this.spectrumPercent + this.spectrumPercentStep);
}
}
};
Spectrum.prototype.decrementSpectrumPercent = function () {
if (this.spectrumPercent - this.spectrumPercentStep >= 0) {
this.setSpectrumPercent(this.spectrumPercent - this.spectrumPercentStep);
}
}
};
Spectrum.prototype.toggleColor = function () {
this.colorindex++;
if (this.colorindex >= colormaps.length)
this.colorindex = 0;
if (this.colorindex >= colormaps.length) this.colorindex = 0;
this.colormap = colormaps[this.colorindex];
this.updateSpectrumRatio();
}
};
Spectrum.prototype.setRange = function (min_db, max_db) {
this.min_db = min_db;
this.max_db = max_db;
this.updateAxes();
}
};
Spectrum.prototype.rangeUp = function () {
this.setRange(this.min_db - 5, this.max_db - 5);
}
};
Spectrum.prototype.rangeDown = function () {
this.setRange(this.min_db + 5, this.max_db + 5);
}
};
Spectrum.prototype.rangeIncrease = function () {
this.setRange(this.min_db - 5, this.max_db + 5);
}
};
Spectrum.prototype.rangeDecrease = function () {
if (this.max_db - this.min_db > 10)
this.setRange(this.min_db + 5, this.max_db - 5);
}
};
Spectrum.prototype.setCenterHz = function (hz) {
this.centerHz = hz;
this.updateAxes();
}
};
Spectrum.prototype.setSpanHz = function (hz) {
this.spanHz = hz;
this.updateAxes();
}
};
Spectrum.prototype.setAveraging = function (num) {
if (num >= 0) {
this.averaging = num;
this.alpha = 2 / (this.averaging + 1)
}
this.alpha = 2 / (this.averaging + 1);
}
};
Spectrum.prototype.incrementAveraging = function () {
this.setAveraging(this.averaging + 1);
}
};
Spectrum.prototype.decrementAveraging = function () {
if (this.averaging > 0) {
this.setAveraging(this.averaging - 1);
}
}
};
Spectrum.prototype.setPaused = function (paused) {
this.paused = paused;
}
};
Spectrum.prototype.togglePaused = function () {
this.setPaused(!this.paused);
}
};
Spectrum.prototype.setMaxHold = function (maxhold) {
this.maxHold = maxhold;
this.binsMax = undefined;
}
};
Spectrum.prototype.toggleMaxHold = function () {
this.setMaxHold(!this.maxHold);
}
};
Spectrum.prototype.toggleFullscreen = function () {
if (!this.fullscreen) {
@ -399,7 +407,7 @@ Spectrum.prototype.toggleFullscreen = function() {
}
this.fullscreen = false;
}
}
};
Spectrum.prototype.onKeypress = function (e) {
if (e.key == " ") {
@ -427,18 +435,20 @@ Spectrum.prototype.onKeypress = function(e) {
} else if (e.key == "m") {
this.toggleMaxHold();
}
}
};
function Spectrum(id, options) {
// Handle options
this.centerHz = (options && options.centerHz) ? options.centerHz : 1500;
this.spanHz = (options && options.spanHz) ? options.spanHz : 0;
this.wf_size = (options && options.wf_size) ? options.wf_size : 0;
this.wf_rows = (options && options.wf_rows) ? options.wf_rows : 1024;
this.spectrumPercent = (options && options.spectrumPercent) ? options.spectrumPercent : 0;
this.spectrumPercentStep = (options && options.spectrumPercentStep) ? options.spectrumPercentStep : 0;
this.averaging = (options && options.averaging) ? options.averaging : 0;
this.maxHold = (options && options.maxHold) ? options.maxHold : false;
this.centerHz = options && options.centerHz ? options.centerHz : 1500;
this.spanHz = options && options.spanHz ? options.spanHz : 0;
this.wf_size = options && options.wf_size ? options.wf_size : 0;
this.wf_rows = options && options.wf_rows ? options.wf_rows : 1024;
this.spectrumPercent =
options && options.spectrumPercent ? options.spectrumPercent : 0;
this.spectrumPercentStep =
options && options.spectrumPercentStep ? options.spectrumPercentStep : 0;
this.averaging = options && options.averaging ? options.averaging : 0;
this.maxHold = options && options.maxHold ? options.maxHold : false;
// Setup state
this.paused = false;

View File

@ -1,4 +1,5 @@
html, body {
html,
body {
width: 100%;
height: 100%;
margin: 0px;

View File

@ -1,10 +1,11 @@
# FreeDV-JATE [Just Another TNC Experiment]
## 002_HIGHSNR_PING_PONG
### INSTALL TEST SUITE
#### Install prerequierements
```
sudo apt update
sudo apt upgrade
@ -15,41 +16,41 @@ pip3 install threading
Go into a directory of your choice
Run the following commands --> They will download and compile the latest codec2 ( dr-packet ) files and LPCNet as well into the directory of your choice
```
wget https://raw.githubusercontent.com/DJ2LS/FreeDV-JATE/002_HIGHSNR_PING_PONG/install_test_suite.sh
chmod +x install_test_suite.sh
./install_test_suite.sh
```
### PARAMETERS
| parameter | description | side
|--|--|--|
| - -txmode 12 | set the mode for FreeDV ( 10,11,12,14 ) | Terminal 1 & Terminal 2
| - -rxmode 14 | set the mode for FreeDV ( 10,11,12,14 ) | Terminal 1 & Terminal 2
| - -frames 1 | set the number of frames per burst | Terminal 1
| - -bursts 1 | set the number of bursts | Terminal 1
| - -audioinput 2 | set the audio device | Terminal 1 & Terminal 2
| - -audiooutput 1 | set the audio device | Terminal 1 & Terminal 2
| - -debug | if used, print additional debugging output | Terminal 1 & Terminal 2
| parameter | description | side |
| ---------------- | ------------------------------------------ | ----------------------- |
| - -txmode 12 | set the mode for FreeDV ( 10,11,12,14 ) | Terminal 1 & Terminal 2 |
| - -rxmode 14 | set the mode for FreeDV ( 10,11,12,14 ) | Terminal 1 & Terminal 2 |
| - -frames 1 | set the number of frames per burst | Terminal 1 |
| - -bursts 1 | set the number of bursts | Terminal 1 |
| - -audioinput 2 | set the audio device | Terminal 1 & Terminal 2 |
| - -audiooutput 1 | set the audio device | Terminal 1 & Terminal 2 |
| - -debug | if used, print additional debugging output | Terminal 1 & Terminal 2 |
### AUDIO TESTS VIA VIRTUAL AUDIO DEVICE
#### Create audio sinkhole and subdevices
Note: This command needs to be run again after every reboot
```
sudo modprobe snd-aloop index=1,2 enable=1,1 pcm_substreams=1,1 id=CHAT1,CHAT2
```
check if devices have been created
aplay -l
Output should be like this:
```
Karte 0: Intel [HDA Intel], Gerät 0: Generic Analog [Generic Analog]
Sub-Geräte: 1/1
@ -71,10 +72,13 @@ Output should be like this:
### Run tests:
#### Terminal 1: Ping
```
python3 PING.py --txmode 12 --rxmode 14 --audioinput 2 --audiooutput 2 --frames 1 --bursts 2
```
Output
```
BURSTS: 2 FRAMES: 1
-----------------------------------------------------------------
@ -86,10 +90,13 @@ RX | PONG | BURST [2/2] FRAME [1/1]
```
#### Terminal 2: Pong
```
python3 PONG.py --txmode 14 --rxmode 12 --audioinput 2 --audiooutput 2
```
Output
```
RX | BURST [1/2] FRAME [1/1] >>> SENDING PONG
RX | BURST [2/2] FRAME [1/1] >>> SENDING PONG

View File

@ -1,7 +1,7 @@
# Unit Test Menu
The following `CTest` tests cover some TNC functionality and the interface to codec2:
1. Name: `audio_buffer`
Tests the thread safety of the audio buffer routines.
1. Name: `resampler`
@ -32,6 +32,7 @@ The following `CTest` tests cover some TNC functionality and the interface to co
The following tests can not currently be run with GitHub's pipeline as they require the ALSA dummy device
kernel module to be installed. They also do not perform reliably. These tests are slowly being
replaced with equivalent pipeline-compatible tests.
1. Name: `highsnr_virtual1_P_P_single_alsa`
Tests a high signal-to-noise ratio audio path using a single codec directly over an ALSA dummy device.
1. Name: `highsnr_virtual2_P_P_single`
@ -46,7 +47,6 @@ replaced with equivalent pipeline-compatible tests.
1. Name: `highsnr_virtual5_P_P_multi_callback`
1. Name: `highsnr_virtual5_P_P_multi_callback_outside`
# Instructions
1. Install:
@ -57,6 +57,7 @@ replaced with equivalent pipeline-compatible tests.
cmake -DCODEC2_BUILD_DIR=$HOME/codec2/build_linux ..
```
2. List available tests:
```
ctest -N
Test project /home/david/FreeDATA/build
@ -65,6 +66,7 @@ replaced with equivalent pipeline-compatible tests.
Total Tests: 2
```
3. Run tests:
```
ctest --output-on-failure
@ -78,7 +80,6 @@ replaced with equivalent pipeline-compatible tests.
ctest -V
```
# 001_HIGHSNR_STDIO_AUDIO TEST SUITE
1. Install
@ -103,18 +104,23 @@ python3 util_tx.py --mode datac1 --delay 500 --frames 2 --bursts 1 | python3 uti
```
## Moderate signal-to-noise ratio (SNR)
Tests need to be written that test a low SNR data path so that the TNC performance when packets are lost can be evaluated.
## AUDIO test via virtual audio devices
### Important:
The virtual audio devices are great for testing, but they are also a little tricky to handle. So there's a high chance, the tests will fail, if you are running them via virtual audio devices. You should run the tests several times, while keeping this in mind. Most time the ctest is working even if it is failing.
1. Create virtual audio devices. Note: This command needs to be run again after every reboot
```
sudo modprobe snd-aloop index=1,2 enable=1,1 pcm_substreams=1,1 id=CHAT1,CHAT2
```
1. Check if devices have been created
```
aplay -l
@ -136,6 +142,7 @@ The virtual audio devices are great for testing, but they are also a little tric
```
1. Determine the audio device number you would like to use:
```
python3 util_rx.py --list
<snip>
@ -148,9 +155,11 @@ The virtual audio devices are great for testing, but they are also a little tric
audiodev: 6 Loopback: PCM (hw:2,0)
audiodev: 7 Loopback: PCM (hw:2,1)
```
In this case we choose audiodev 4 for the RX and 5 for the Tx.
1. Start the Rx first, then Tx in separate consoles:
```
python3 util_rx.py --mode datac0 --frames 2 --bursts 1 --audiodev 4 --debug
python3 util_tx.py --mode datac0 --frames 2 --bursts 1 --audiodev 5
```

View File

@ -1,3 +1,5 @@
# PyAudio
## downloaded from
https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio