some code linting

This commit is contained in:
DJ2LS 2023-10-03 15:15:17 +02:00
parent b49c223dd2
commit 37c176ff41
42 changed files with 5124 additions and 5363 deletions

View file

@ -7,7 +7,9 @@
"start": "vite",
"dev": "vite",
"build": "vue-tsc && vite build && electron-builder",
"preview": "vite preview"
"preview": "vite preview",
"lint": "eslint --ext .js,.vue src",
"lint-fix": "eslint --ext .js,.vue --fix src"
},
"dependencies": {
"@vueuse/electron": "^10.4.1",
@ -36,10 +38,19 @@
"winston": "^3.10.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@vitejs/plugin-vue": "^4.1.0",
"electron": "^24.8.2",
"electron-builder": "^23.6.0",
"typescript": "^5.0.2",
"eslint": "^8.50.0",
"eslint-config-prettier": "^9.0.0",
"eslint-config-standard-with-typescript": "^39.1.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-n": "^16.1.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-vue": "^9.17.0",
"typescript": "^5.2.2",
"vite": "^4.3.2",
"vite-plugin-electron": "^0.11.2",
"vite-plugin-electron-renderer": "^0.14.5",

View file

@ -1,16 +1,7 @@
<script setup lang="ts">
import FreeDATAMain from './components/main.vue'
import FreeDATAMain from "./components/main.vue";
</script>
<template>
<FreeDATAMain/>
<FreeDATAMain />
</template>

View file

@ -1,50 +1,40 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler';
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import { useChatStore } from '../store/chatStore.js';
import { useChatStore } from "../store/chatStore.js";
const chat = useChatStore(pinia);
import chat_navbar from "./chat_navbar.vue";
import chat_conversations from "./chat_conversations.vue";
import chat_messages from "./chat_messages.vue";
import chat_new_message from "./chat_new_message.vue";
import chat_navbar from './chat_navbar.vue'
import chat_conversations from './chat_conversations.vue'
import chat_messages from './chat_messages.vue'
import chat_new_message from './chat_new_message.vue'
import {updateAllChat, newMessage} from '../js/chatHandler'
updateAllChat()
import { updateAllChat, newMessage } from "../js/chatHandler";
updateAllChat();
</script>
<template>
<div class="container-fluid m-0 p-0">
<div class="container-fluid m-0 p-0">
<!------ chat navbar ---------------------------------------------------------------------->
<chat_navbar/>
<chat_navbar />
<div class="row h-100 ms-0 mt-0 me-1">
<div class="col-3 m-0 p-0 bg-light">
<!------Chats area ---------------------------------------------------------------------->
<div class="container-fluid m-0 p-0">
<chat_conversations/>
<chat_conversations />
</div>
<div class="overflow-auto vh-100">
<div
@ -74,20 +64,16 @@ updateAllChat()
id="message-container"
style="height: calc(100% - 200px)"
>
<chat_messages/>
<chat_messages />
</div>
<!------ new message area ---------------------------------------------------------------------->
<chat_new_message/>
<chat_new_message />
</div>
</div>
</div>
<!-- user modal -->
<div
@ -115,10 +101,7 @@ updateAllChat()
class="col position-absolute image-overlay text-white justify-content-center align-items-center d-flex align-middle h-100 opacity-0"
id="userImageSelector"
>
<i
class="bi bi-upload"
style="font-size: 2.2rem"
></i>
<i class="bi bi-upload" style="font-size: 2.2rem"></i>
</div>
</div>
</div>
@ -298,39 +281,32 @@ updateAllChat()
class="badge bg-secondary"
id="dx_user_info_name"
></span>
<span
class="badge bg-secondary"
id="dx_user_info_age"
></span>
<span class="badge bg-secondary" id="dx_user_info_age"></span>
</h5>
<ul class="card-text list-unstyled">
<li>
<strong class="col"
><i class="bi bi-house"></i> </strong
><span id="dx_user_info_location"></span>
(<span id="dx_user_info_gridsquare"></span>)
<strong class="col"><i class="bi bi-house"></i> </strong
><span id="dx_user_info_location"></span> (<span
id="dx_user_info_gridsquare"
></span
>)
</li>
<li>
<strong class="col"
><i class="bi bi-envelope"></i> </strong
<strong class="col"><i class="bi bi-envelope"></i> </strong
><span id="dx_user_info_email"></span>
</li>
<li>
<strong class="col"
><i class="bi bi-globe"></i> </strong
<strong class="col"><i class="bi bi-globe"></i> </strong
><span id="dx_user_info_website"></span>
</li>
<li>
<strong class="col"
><i
class="bi bi-broadcast-pin"
></i> </strong
><i class="bi bi-broadcast-pin"></i> </strong
><span id="dx_user_info_antenna"></span>
</li>
<li>
<strong class="col"
><i class="bi bi-projector"></i> </strong
<strong class="col"><i class="bi bi-projector"></i> </strong
><span id="dx_user_info_radio"></span>
</li>
<li>
@ -378,10 +354,7 @@ updateAllChat()
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h1
class="modal-title fs-5"
id="sharedFolderModalLabel"
>
<h1 class="modal-title fs-5" id="sharedFolderModalLabel">
My Shared folder
<button
type="button"
@ -404,8 +377,7 @@ updateAllChat()
<div class="container-fluid p-0">
<div class="center mb-1">
<div class="badge text-bg-info">
<i class="bi bi-info"></i> Change folder in
settings!
<i class="bi bi-info"></i> Change folder in settings!
</div>
</div>
<div class="table-responsive">
@ -451,29 +423,22 @@ updateAllChat()
<div class="card mb-3">
<div class="card-body">
<p class="card-text">
Welcome to the chat window. Heard stations are
listed in the list on the left. Clicking on a
station will show messages sent and/or received
from the selected station. Additional help is
Welcome to the chat window. Heard stations are listed in the
list on the left. Clicking on a station will show messages sent
and/or received from the selected station. Additional help is
available on various extra features below.
</p>
</div>
</div>
<div class="card mb-3">
<div class="card-body">
<button
type="button"
class="btn btn-sm btn-primary ms-2"
>
<i
class="bi bi-person"
style="font-size: 1.2rem"
></i>
<button type="button" class="btn btn-sm btn-primary ms-2">
<i class="bi bi-person" style="font-size: 1.2rem"></i>
</button>
<p class="card-text">
Set your station information and picture. This
information can be requested by a remote station
and can be enabled/disabled via settings.
Set your station information and picture. This information can
be requested by a remote station and can be enabled/disabled via
settings.
</p>
</div>
</div>
@ -483,10 +448,7 @@ updateAllChat()
type="button"
class="btn btn-sm btn-outline-secondary ms-2"
>
<i
class="bi bi-person"
style="font-size: 1.2rem"
></i>
<i class="bi bi-person" style="font-size: 1.2rem"></i>
</button>
<p class="card-text">
Request the selected station's information.
@ -499,25 +461,15 @@ updateAllChat()
type="button"
class="btn btn-sm btn-outline-secondary ms-2"
>
<i
class="bi bi-files"
style="font-size: 1.2rem"
></i>
<i class="bi bi-files" style="font-size: 1.2rem"></i>
</button>
<p class="card-text">
Request the selected station's shared file(s)
list. Clicking
<button
type="button"
class="btn btn-sm btn-primary ms-2"
>
<i
class="bi bi-files"
style="font-size: 1.2rem"
></i>
Request the selected station's shared file(s) list. Clicking
<button type="button" class="btn btn-sm btn-primary ms-2">
<i class="bi bi-files" style="font-size: 1.2rem"></i>
</button>
will allow you to preview your shared files.
Shared file can be enabled/disabled in settings.
will allow you to preview your shared files. Shared file can be
enabled/disabled in settings.
</p>
</div>
</div>
@ -530,10 +482,9 @@ updateAllChat()
<i class="bi bi-funnel-fill"></i>
</button>
<p class="card-text">
The filter button allows you to show or hide
certain types of messages. A lot of data is logged
and this allows you to modify what is shown. By
default sent and received messages and ping
The filter button allows you to show or hide certain types of
messages. A lot of data is logged and this allows you to modify
what is shown. By default sent and received messages and ping
acknowlegements are displayed.
</p>
</div>
@ -553,10 +504,7 @@ updateAllChat()
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h1
class="modal-title fs-5"
id="sharedFolderModalDXLabel"
>
<h1 class="modal-title fs-5" id="sharedFolderModalDXLabel">
Shared folder
</h1>
<button
@ -601,7 +549,4 @@ updateAllChat()
</div>
</div>
</div>
</template>

View file

@ -1,77 +1,75 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler';
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import {deleteChatByCallsign} from '../js/chatHandler'
import { deleteChatByCallsign } from "../js/chatHandler";
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import { useChatStore } from '../store/chatStore.js';
import { useChatStore } from "../store/chatStore.js";
const chat = useChatStore(pinia);
function deleteChat(callsign){
deleteChatByCallsign(callsign)
function deleteChat(callsign) {
deleteChatByCallsign(callsign);
}
import chat_conversations_entry from "./chat_conversations_entry.vue";
import chat_conversations_entry from './chat_conversations_entry.vue'
function chatSelected(callsign){
chat.selectedCallsign = callsign.toUpperCase()
function chatSelected(callsign) {
chat.selectedCallsign = callsign.toUpperCase();
// scroll message container to bottom
var messageBody = document.getElementById("message-container");
messageBody.scrollTop = messageBody.scrollHeight - messageBody.clientHeight;
try{
chat.beaconLabelArray = Object.values(chat.sorted_beacon_list[chat.selectedCallsign].timestamp)
chat.beaconDataArray = Object.values(chat.sorted_beacon_list[chat.selectedCallsign].snr)
} catch(e){
console.log("beacon data not fetched: " + e)
chat.beaconLabelArray = []
chat.beaconDataArray = []
try {
chat.beaconLabelArray = Object.values(
chat.sorted_beacon_list[chat.selectedCallsign].timestamp,
);
chat.beaconDataArray = Object.values(
chat.sorted_beacon_list[chat.selectedCallsign].snr,
);
} catch (e) {
console.log("beacon data not fetched: " + e);
chat.beaconLabelArray = [];
chat.beaconDataArray = [];
}
console.log(chat.beaconDataArray)
console.log(chat.beaconDataArray);
}
</script>
<template>
<div class="list-group m-0 p-0" id="chat-list-tab" role="chat-tablist">
<div class="list-group m-0 p-0" id="chat-list-tab" role="chat-tablist">
<template v-for="(item, key) in chat.callsign_list" :key="item.dxcallsign">
<a class="list-group-item list-group-item-action border-0 border-bottom rounded-0" :class="{ active: key==0 }" :id="`list-chat-list-${item}`" data-bs-toggle="list" :href="`#list-${item}-messages`" role="tab" aria-controls="list-{{item}}-messages" @click="chatSelected(item)">
<a
class="list-group-item list-group-item-action border-0 border-bottom rounded-0"
:class="{ active: key == 0 }"
:id="`list-chat-list-${item}`"
data-bs-toggle="list"
:href="`#list-${item}-messages`"
role="tab"
aria-controls="list-{{item}}-messages"
@click="chatSelected(item)"
>
<div class="row">
<div class="col-9">{{item}}</div>
<div class="col-9">{{ item }}</div>
<div class="col-3">
<button class="btn btn-sm btn-outline-danger ms-2" @click="deleteChat(item)"><i class="bi bi-trash"></i></button>
<button
class="btn btn-sm btn-outline-danger ms-2"
@click="deleteChat(item)"
>
<i class="bi bi-trash"></i>
</button>
</div>
</div>
</a>
</template>
<!--<chat_conversations_entry/>-->
</div>
</div>
</template>

View file

@ -1,30 +1,28 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler';
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import { useChatStore } from '../store/chatStore.js';
import { useChatStore } from "../store/chatStore.js";
const chat = useChatStore(pinia);
import SentMessage from './chat_messages_sent.vue'; // Import the chat_messages_sent component
import ReceivedMessage from './chat_messages_received.vue'; // Import the chat_messages_sent component
import ReceivedBroadcastMessage from './chat_messages_broadcast_received.vue'; // Import the chat_messages_sent component for broadcasts
import SentBroadcastMessage from './chat_messages_broadcast_sent.vue'; // Import the chat_messages_sent component for broadcasts
import SentMessage from "./chat_messages_sent.vue"; // Import the chat_messages_sent component
import ReceivedMessage from "./chat_messages_received.vue"; // Import the chat_messages_sent component
import ReceivedBroadcastMessage from "./chat_messages_broadcast_received.vue"; // Import the chat_messages_sent component for broadcasts
import SentBroadcastMessage from "./chat_messages_broadcast_sent.vue"; // Import the chat_messages_sent component for broadcasts
//helper function for saving the last messages day for disaplying the day based divider
var prevChatMessageDay = ''
var prevChatMessageDay = "";
function getDateTime(timestampRaw){
function getDateTime(timestampRaw) {
var datetime = new Date(timestampRaw * 1000).toLocaleString(
navigator.language,
{
@ -34,43 +32,50 @@ function getDateTime(timestampRaw){
day: "2-digit",
},
);
return datetime
return datetime;
}
</script>
<template>
<div class="tab-content" id="nav-tabContent-chat-messages">
<template v-for="(callsign, key) in chat.callsign_list">
<div class="tab-pane fade show" :class="{ active: key==0 }" :id="`list-${callsign}-messages`" role="tabpanel" :aria-labelledby="`list-chat-list-${callsign}`">
<template v-for="item in chat.sorted_chat_list[callsign]" :key="item._id">
<div
class="tab-pane fade show"
:class="{ active: key == 0 }"
:id="`list-${callsign}-messages`"
role="tabpanel"
:aria-labelledby="`list-chat-list-${callsign}`"
>
<template
v-for="item in chat.sorted_chat_list[callsign]"
:key="item._id"
>
<div v-if="prevChatMessageDay !== getDateTime(item.timestamp)">
<div class="separator my-2">{{prevChatMessageDay = getDateTime(item.timestamp)}}</div>
<div class="separator my-2">
{{ (prevChatMessageDay = getDateTime(item.timestamp)) }}
</div>
</div>
<div v-if="item.type === 'beacon' && item.status === 'received'">
{{item}}
{{ item }}
</div>
<div v-if="item.type === 'ping'">
{{item.snr}}
{{ item.snr }}
{{chat.beaconDataArray}}
{{ chat.beaconDataArray }}
</div>
<div v-if="item.type === 'ping-ack'">
{{item.snr}}
{{ item.snr }}
{{chat.beaconDataArray}}
{{ chat.beaconDataArray }}
</div>
<div v-if="item.type === 'transmit'">
<sent-message :message="item" />
</div>
<div v-else-if="item.type === 'received'">
<received-message :message="item" />
</div>
<div v-if="item.type === 'broadcast_transmit'">
@ -79,18 +84,13 @@ return datetime
<div v-else-if="item.type === 'broadcast_received'">
<received-broadcast-message :message="item" />
</div>
</template>
</div>
</template>
</div>
</template>
<style>
/* https://stackoverflow.com/a/26634224 */
.separator {
display: flex;
@ -100,16 +100,16 @@ return datetime
.separator::before,
.separator::after {
content: '';
content: "";
flex: 1;
border-bottom: 1px solid #000;
}
.separator:not(:empty)::before {
margin-right: .25em;
margin-right: 0.25em;
}
.separator:not(:empty)::after {
margin-left: .25em;
margin-left: 0.25em;
}
</style>

View file

@ -12,15 +12,15 @@ export default {
methods: {
onDelete() {
// Implement delete action
this.$emit('delete');
this.$emit("delete");
},
onCopy() {
// Implement copy action
this.$emit('copy');
this.$emit("copy");
},
onQuote() {
// Implement quote action
this.$emit('quote');
this.$emit("quote");
},
},
};

View file

@ -2,9 +2,12 @@
<div class="row justify-content-start mb-2">
<div :class="messageWidthClass">
<div class="card bg-light border-0 text-dark">
<div class="card-header" v-if="getFileContent['filesize'] !== 0">
<p class="card-text">{{ getFileContent["filename"] }} | {{ getFileContent["filesize"] }} Bytes | {{ getFileContent["filetype"] }}</p>
<p class="card-text">
{{ getFileContent["filename"] }} |
{{ getFileContent["filesize"] }} Bytes |
{{ getFileContent["filetype"] }}
</p>
</div>
<div class="card-body">
@ -12,81 +15,79 @@
</div>
<div class="card-footer p-0 bg-light border-top-0">
<p class="text-muted p-0 m-0 me-1 text-end">{{ getDateTime }}</p> <!-- Display formatted timestamp in card-footer -->
<p class="text-muted p-0 m-0 me-1 text-end">{{ getDateTime }}</p>
<!-- Display formatted timestamp in card-footer -->
</div>
<span class="position-absolute top-0 start-100 translate-middle badge rounded-1 bg-secondary border border-white">
{{message.broadcast_sender}}
<span
class="position-absolute top-0 start-100 translate-middle badge rounded-1 bg-secondary border border-white"
>
{{ message.broadcast_sender }}
</span>
</div>
</div>
<!-- Delete button outside of the card -->
<div class="col-auto">
<button class="btn btn-outline-secondary border-0" @click="deleteMessage"><i class="bi bi-trash"></i></button>
<button class="btn btn-outline-secondary border-0" @click="deleteMessage">
<i class="bi bi-trash"></i>
</button>
</div>
</div>
</template>
<script>
import {deleteMessageFromDB} from '../js/chatHandler'
import { deleteMessageFromDB } from "../js/chatHandler";
export default {
props: {
message: Object,
},
computed: {
getFileContent(){
try{
var filename = Object.keys(this.message._attachments)[0]
var filesize = this.message._attachments[filename]["length"]
var filetype = filename.split(".")[1]
getFileContent() {
try {
var filename = Object.keys(this.message._attachments)[0];
var filesize = this.message._attachments[filename]["length"];
var filetype = filename.split(".")[1];
// ensure filesize is 0 for hiding message header if no data is available
if (typeof filename === 'undefined' || filename === '' || filename === '-' || filename === 'null'){
filesize = 0
if (
typeof filename === "undefined" ||
filename === "" ||
filename === "-" ||
filename === "null"
) {
filesize = 0;
}
return {filename: filename, filesize: filesize, filetype: filetype}
} catch (e){
console.log("file not loaded from database - empty?")
return { filename: filename, filesize: filesize, filetype: filetype };
} catch (e) {
console.log("file not loaded from database - empty?");
// we are only checking against filesize for displaying attachments
return {filesize: 0}
return { filesize: 0 };
}
},
messageWidthClass() {
// Calculate a Bootstrap grid class based on message length
// Adjust the logic as needed to fit your requirements
if (this.message.msg.length <= 50) {
return 'col-4';
return "col-4";
} else if (this.message.msg.length <= 100) {
return 'col-6';
return "col-6";
} else {
return 'col-9';
return "col-9";
}
},
deleteMessage(){
deleteMessageFromDB(this.message._id)
deleteMessage() {
deleteMessageFromDB(this.message._id);
},
getDateTime() {
var datetime = new Date(this.message.timestamp * 1000).toLocaleString(
navigator.language,
{
hour: '2-digit',
minute: '2-digit',
}
hour: "2-digit",
minute: "2-digit",
},
);
return datetime;
},

View file

@ -2,17 +2,26 @@
<div class="row justify-content-end mb-2">
<!-- control area -->
<div class="col-auto p-0 m-0">
<button class="btn btn-outline-secondary border-0 me-1" @click="repeatMessage"><i class="bi bi-arrow-repeat"></i></button>
<button class="btn btn-outline-secondary border-0" @click="deleteMessage"><i class="bi bi-trash"></i></button>
<button
class="btn btn-outline-secondary border-0 me-1"
@click="repeatMessage"
>
<i class="bi bi-arrow-repeat"></i>
</button>
<button class="btn btn-outline-secondary border-0" @click="deleteMessage">
<i class="bi bi-trash"></i>
</button>
</div>
<!-- message area -->
<div :class="messageWidthClass">
<div class="card bg-primary text-white">
<div class="card-header" v-if="getFileContent['filesize'] !== 0">
<p class="card-text">{{ getFileContent["filename"] }} | {{ getFileContent["filesize"] }} Bytes | {{ getFileContent["filetype"] }}</p>
<p class="card-text">
{{ getFileContent["filename"] }} |
{{ getFileContent["filesize"] }} Bytes |
{{ getFileContent["filetype"] }}
</p>
</div>
<div class="card-body">
@ -20,7 +29,8 @@
</div>
<div class="card-footer p-0 bg-primary border-top-0">
<p class="text p-0 m-0 me-1 text-end">{{ getDateTime }}</p> <!-- Display formatted timestamp in card-footer -->
<p class="text p-0 m-0 me-1 text-end">{{ getDateTime }}</p>
<!-- Display formatted timestamp in card-footer -->
</div>
<div class="card-footer p-0 border-top-0" v-if="message.percent < 100">
@ -42,63 +52,59 @@
</div>
</template>
<script>
import {repeatMessageTransmission, deleteMessageFromDB} from '../js/chatHandler'
import {
repeatMessageTransmission,
deleteMessageFromDB,
} from "../js/chatHandler";
export default {
props: {
message: Object,
},
computed: {
getFileContent(){
var filename = Object.keys(this.message._attachments)[0]
var filesize = this.message._attachments[filename]["length"]
var filetype = filename.split(".")[1]
getFileContent() {
var filename = Object.keys(this.message._attachments)[0];
var filesize = this.message._attachments[filename]["length"];
var filetype = filename.split(".")[1];
// ensure filesize is 0 for hiding message header if no data is available
if (typeof filename === 'undefined' || filename === '' || filename === '-' || filename === 'null'){
filesize = 0
if (
typeof filename === "undefined" ||
filename === "" ||
filename === "-" ||
filename === "null"
) {
filesize = 0;
}
return {filename: filename, filesize: filesize, filetype: filetype}
return { filename: filename, filesize: filesize, filetype: filetype };
},
messageWidthClass() {
// Calculate a Bootstrap grid class based on message length
// Adjust the logic as needed to fit your requirements
if (this.message.msg.length <= 50) {
return 'col-4';
return "col-4";
} else if (this.message.msg.length <= 100) {
return 'col-6';
return "col-6";
} else {
return 'col-9';
return "col-9";
}
},
repeatMessage(){
repeatMessageTransmission(this.message._id)
repeatMessage() {
repeatMessageTransmission(this.message._id);
},
deleteMessage(){
deleteMessageFromDB(this.message._id)
deleteMessage() {
deleteMessageFromDB(this.message._id);
},
getDateTime() {
var datetime = new Date(this.message.timestamp * 1000).toLocaleString(
navigator.language,
{
hour: '2-digit',
minute: '2-digit',
}
hour: "2-digit",
minute: "2-digit",
},
);
return datetime;
},

View file

@ -2,9 +2,12 @@
<div class="row justify-content-start mb-2">
<div :class="messageWidthClass">
<div class="card bg-light border-0 text-dark">
<div class="card-header" v-if="getFileContent['filesize'] !== 0">
<p class="card-text">{{ getFileContent["filename"] }} | {{ getFileContent["filesize"] }} Bytes | {{ getFileContent["filetype"] }}</p>
<p class="card-text">
{{ getFileContent["filename"] }} |
{{ getFileContent["filesize"] }} Bytes |
{{ getFileContent["filetype"] }}
</p>
</div>
<div class="card-body">
@ -12,67 +15,63 @@
</div>
<div class="card-footer p-0 bg-light border-top-0">
<p class="text-muted p-0 m-0 me-1 text-end">{{ getDateTime }}</p> <!-- Display formatted timestamp in card-footer -->
<p class="text-muted p-0 m-0 me-1 text-end">{{ getDateTime }}</p>
<!-- Display formatted timestamp in card-footer -->
</div>
</div>
</div>
<!-- Delete button outside of the card -->
<div class="col-auto">
<button class="btn btn-outline-secondary border-0" @click="deleteMessage"><i class="bi bi-trash"></i></button>
<button class="btn btn-outline-secondary border-0" @click="deleteMessage">
<i class="bi bi-trash"></i>
</button>
</div>
</div>
</template>
<script>
import {deleteMessageFromDB} from '../js/chatHandler'
import { deleteMessageFromDB } from "../js/chatHandler";
export default {
props: {
message: Object,
},
computed: {
getFileContent(){
try{
var filename = Object.keys(this.message._attachments)[0]
var filesize = this.message._attachments[filename]["length"]
var filetype = filename.split(".")[1]
getFileContent() {
try {
var filename = Object.keys(this.message._attachments)[0];
var filesize = this.message._attachments[filename]["length"];
var filetype = filename.split(".")[1];
return {filename: filename, filesize: filesize, filetype: filetype}
} catch (e){
console.log("file not loaded from database - empty?")
return { filename: filename, filesize: filesize, filetype: filetype };
} catch (e) {
console.log("file not loaded from database - empty?");
// we are only checking against filesize for displaying attachments
return {filesize: 0}
return { filesize: 0 };
}
},
messageWidthClass() {
// Calculate a Bootstrap grid class based on message length
// Adjust the logic as needed to fit your requirements
if (this.message.msg.length <= 50) {
return 'col-4';
return "col-4";
} else if (this.message.msg.length <= 100) {
return 'col-6';
return "col-6";
} else {
return 'col-9';
return "col-9";
}
},
deleteMessage(){
deleteMessageFromDB(this.message._id)
deleteMessage() {
deleteMessageFromDB(this.message._id);
},
getDateTime() {
var datetime = new Date(this.message.timestamp * 1000).toLocaleString(
navigator.language,
{
hour: '2-digit',
minute: '2-digit',
}
hour: "2-digit",
minute: "2-digit",
},
);
return datetime;
},

View file

@ -2,17 +2,26 @@
<div class="row justify-content-end mb-2">
<!-- control area -->
<div class="col-auto p-0 m-0">
<button class="btn btn-outline-secondary border-0 me-1" @click="repeatMessage"><i class="bi bi-arrow-repeat"></i></button>
<button class="btn btn-outline-secondary border-0" @click="deleteMessage"><i class="bi bi-trash"></i></button>
<button
class="btn btn-outline-secondary border-0 me-1"
@click="repeatMessage"
>
<i class="bi bi-arrow-repeat"></i>
</button>
<button class="btn btn-outline-secondary border-0" @click="deleteMessage">
<i class="bi bi-trash"></i>
</button>
</div>
<!-- message area -->
<div :class="messageWidthClass">
<div class="card bg-primary text-white">
<div class="card-header" v-if="getFileContent['filesize'] !== 0">
<p class="card-text">{{ getFileContent["filename"] }} | {{ getFileContent["filesize"] }} Bytes | {{ getFileContent["filetype"] }}</p>
<p class="card-text">
{{ getFileContent["filename"] }} |
{{ getFileContent["filesize"] }} Bytes |
{{ getFileContent["filetype"] }}
</p>
</div>
<div class="card-body">
@ -20,11 +29,15 @@
</div>
<div class="card-footer p-0 bg-primary border-top-0">
<p class="text p-0 m-0 me-1 text-end">{{ getDateTime }}</p> <!-- Display formatted timestamp in card-footer -->
<p class="text p-0 m-0 me-1 text-end">{{ getDateTime }}</p>
<!-- Display formatted timestamp in card-footer -->
</div>
<div class="card-footer p-0 border-top-0" v-if="message.percent < 100">
<div class="progress bg-secondary rounded-0 rounded-bottom" :style="{ height: '10px' }">
<div
class="progress bg-secondary rounded-0 rounded-bottom"
:style="{ height: '10px' }"
>
<div
class="progress-bar progress-bar-striped overflow-visible"
role="progressbar"
@ -42,63 +55,58 @@
</div>
</template>
<script>
import {repeatMessageTransmission, deleteMessageFromDB} from '../js/chatHandler'
import {
repeatMessageTransmission,
deleteMessageFromDB,
} from "../js/chatHandler";
export default {
props: {
message: Object,
},
computed: {
getFileContent(){
var filename = Object.keys(this.message._attachments)[0]
var filesize = this.message._attachments[filename]["length"]
var filetype = filename.split(".")[1]
getFileContent() {
var filename = Object.keys(this.message._attachments)[0];
var filesize = this.message._attachments[filename]["length"];
var filetype = filename.split(".")[1];
// ensure filesize is 0 for hiding message header if no data is available
if (typeof filename === 'undefined' || filename === '' || filename === '-'){
filesize = 0
if (
typeof filename === "undefined" ||
filename === "" ||
filename === "-"
) {
filesize = 0;
}
return {filename: filename, filesize: filesize, filetype: filetype}
return { filename: filename, filesize: filesize, filetype: filetype };
},
messageWidthClass() {
// Calculate a Bootstrap grid class based on message length
// Adjust the logic as needed to fit your requirements
if (this.message.msg.length <= 50) {
return 'col-4';
return "col-4";
} else if (this.message.msg.length <= 100) {
return 'col-6';
return "col-6";
} else {
return 'col-9';
return "col-9";
}
},
repeatMessage(){
repeatMessageTransmission(this.message._id)
repeatMessage() {
repeatMessageTransmission(this.message._id);
},
deleteMessage(){
deleteMessageFromDB(this.message._id)
deleteMessage() {
deleteMessageFromDB(this.message._id);
},
getDateTime() {
var datetime = new Date(this.message.timestamp * 1000).toLocaleString(
navigator.language,
{
hour: '2-digit',
minute: '2-digit',
}
hour: "2-digit",
minute: "2-digit",
},
);
return datetime;
},

View file

@ -1,19 +1,17 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler';
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import { useChatStore } from '../store/chatStore.js';
import { useChatStore } from "../store/chatStore.js";
const chat = useChatStore(pinia);
import {
@ -25,11 +23,10 @@ import {
Title,
Tooltip,
Legend,
BarElement
} from 'chart.js'
import { Line, Scatter, Bar } from 'vue-chartjs'
import { ref, computed } from 'vue';
BarElement,
} from "chart.js";
import { Line, Scatter, Bar } from "vue-chartjs";
import { ref, computed } from "vue";
ChartJS.register(
CategoryScale,
@ -38,21 +35,21 @@ ChartJS.register(
Title,
Tooltip,
Legend,
BarElement
)
BarElement,
);
var beaconHistogramOptions = {
type: 'bar',
bezierCurve:false, //remove curves from your plot
scaleShowLabels : false, //remove labels
tooltipEvents:[], //remove trigger from tooltips so they will'nt be show
pointDot : false, //remove the points markers
var beaconHistogramOptions = {
type: "bar",
bezierCurve: false, //remove curves from your plot
scaleShowLabels: false, //remove labels
tooltipEvents: [], //remove trigger from tooltips so they will'nt be show
pointDot: false, //remove the points markers
scaleShowGridLines: true, //set to false to remove the grids background
maintainAspectRatio:true,
plugins:{
maintainAspectRatio: true,
plugins: {
legend: {
display: false
}
display: false,
},
},
scales: {
@ -63,7 +60,7 @@ ChartJS.register(
max: 15,
ticks: {
display: false,
}
},
},
y: {
display: false,
@ -71,10 +68,10 @@ ChartJS.register(
max: 10,
ticks: {
display: false,
}
},
},
};
},
};
//let dataArray = new Array(25).fill(0)
//dataArray = dataArray.add([-3, 10, 8, 5, 3, 0, -5])
@ -82,62 +79,34 @@ ChartJS.register(
//console.log(dataArray1)
//[-3, 10, 8, 5, 3, 0, -5]
try {
chat.beaconLabelArray = Object.values(
chat.sorted_beacon_list["DJ2LS-0"].timestamp,
);
chat.beaconDataArray = Object.values(chat.sorted_beacon_list["DJ2LS-0"].snr);
} catch (e) {
console.log(e);
try{
chat.beaconLabelArray = Object.values(chat.sorted_beacon_list['DJ2LS-0'].timestamp)
chat.beaconDataArray = Object.values(chat.sorted_beacon_list['DJ2LS-0'].snr)
} catch(e){
console.log(e)
var beaconLabels = []
var beaconData = []
var beaconLabels = [];
var beaconData = [];
}
const beaconHistogramData = computed(() => ({
labels: chat.beaconLabelArray,
datasets: [
{ data: chat.beaconDataArray, tension: 0.1, borderColor: 'rgb(0, 255, 0)' }
]
{ data: chat.beaconDataArray, tension: 0.1, borderColor: "rgb(0, 255, 0)" },
],
}));
function newChat(obj) {
let callsign = document.getElementById("chatModuleNewDxCall").value;
callsign = callsign.toUpperCase();
chat.callsign_list.add(callsign);
}
));
function newChat(obj){
let callsign = document.getElementById("chatModuleNewDxCall").value
callsign = callsign.toUpperCase()
chat.callsign_list.add(callsign)
}
</script>
<template>
<nav class="navbar bg-body-tertiary border-bottom">
<nav class="navbar bg-body-tertiary border-bottom">
<div class="container">
<div class="row w-100">
<div class="col-4 p-0 me-2">
@ -157,23 +126,19 @@ function newChat(obj){
@click="newChat()"
>
new chat
<i
class="bi bi-pencil-square"
style="font-size: 1.2rem"
></i>
<i class="bi bi-pencil-square" style="font-size: 1.2rem"></i>
</button>
</div>
</div>
<div class="col-7 ms-2 p-0">
<!-- right side of chat nav bar-->
{{beaconData}}
<Bar :data="beaconHistogramData" :options="beaconHistogramOptions" width="300" style="height:100%" />
{{ beaconData }}
<Bar
:data="beaconHistogramData"
:options="beaconHistogramOptions"
width="300"
style="height: 100%"
/>
</div>
</div>
</div>

View file

@ -1,46 +1,34 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import main_modals from './main_modals.vue'
import main_top_navbar from './main_top_navbar.vue'
import main_audio from './main_audio.vue'
import main_rig_control from './main_rig_control.vue'
import main_my_station from './main_my_station.vue'
import main_updater from './main_updater.vue'
import settings_view from './settings.vue'
import main_active_rig_control from './main_active_rig_control.vue'
import main_footer_navbar from './main_footer_navbar.vue'
import main_active_stats from './main_active_stats.vue'
import main_active_broadcasts from './main_active_broadcasts.vue'
import main_active_heard_stations from './main_active_heard_stations.vue'
import main_active_audio_level from './main_active_audio_level.vue'
import chat from './chat.vue'
import {stopTransmission} from '../js/sock.js'
import main_modals from "./main_modals.vue";
import main_top_navbar from "./main_top_navbar.vue";
import main_audio from "./main_audio.vue";
import main_rig_control from "./main_rig_control.vue";
import main_my_station from "./main_my_station.vue";
import main_updater from "./main_updater.vue";
import settings_view from "./settings.vue";
import main_active_rig_control from "./main_active_rig_control.vue";
import main_footer_navbar from "./main_footer_navbar.vue";
import main_active_stats from "./main_active_stats.vue";
import main_active_broadcasts from "./main_active_broadcasts.vue";
import main_active_heard_stations from "./main_active_heard_stations.vue";
import main_active_audio_level from "./main_active_audio_level.vue";
import chat from "./chat.vue";
import { stopTransmission } from "../js/sock.js";
function changeGuiDesign(design) {
if (
@ -105,16 +93,10 @@ function changeGuiDesign(design) {
document.getElementById("bootstrap_theme").href = escape(theme_path);
}
function stopAllTransmissions(){
console.log("stopping transmissions")
stopTransmission()
function stopAllTransmissions() {
console.log("stopping transmissions");
stopTransmission();
}
</script>
<template>
@ -164,7 +146,6 @@ function stopAllTransmissions(){
><i class="bi bi-chat-text h3"></i
></a>
<a
class="list-group-item list-group-item-action d-none"
id="list-mesh-list"
@ -185,7 +166,6 @@ function stopAllTransmissions(){
><i class="bi bi-info h3"></i
></a>
<a
class="list-group-item list-group-item-action d-none"
id="list-logger-list"
@ -402,7 +382,6 @@ function stopAllTransmissions(){
</div>
</div>
<div
class="tab-pane fade"
id="nav-actions"
@ -537,10 +516,7 @@ function stopAllTransmissions(){
role="tabpanel"
aria-labelledby="list-chat-list"
>
<chat/>
<chat />
</div>
<div
class="tab-pane fade"

View file

@ -1,32 +1,26 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import {record_audio, sendTestFrame} from '../js/sock.js'
import { record_audio, sendTestFrame } from "../js/sock.js";
function startStopRecordAudio(){
record_audio()
function startStopRecordAudio() {
record_audio();
}
</script>
<template>
<div class="card mb-1">
<div class="card mb-1">
<div class="card-header p-1">
<div class="container">
<div class="row">
<div class="col-1">
<i class="bi bi-volume-up" style="font-size: 1.2rem"></i>
@ -49,8 +43,10 @@ function startStopRecordAudio(){
id="startStopRecording"
class="btn btn-sm"
@click="startStopRecordAudio()"
v-bind:class="{ 'btn-outline-secondary' : state.audio_recording === 'False',
'btn-secondary' : state.audio_recording === 'True'}"
v-bind:class="{
'btn-outline-secondary': state.audio_recording === 'False',
'btn-secondary': state.audio_recording === 'True',
}"
>
Record
</button>
@ -63,10 +59,7 @@ function startStopRecordAudio(){
data-bs-target="#audioLevelHelpModal"
class="btn m-0 p-0 border-0"
>
<i
class="bi bi-question-circle"
style="font-size: 1rem"
></i>
<i class="bi bi-question-circle" style="font-size: 1rem"></i>
</button>
</div>
</div>
@ -76,7 +69,10 @@ function startStopRecordAudio(){
<div class="container">
<div class="row">
<div class="col-sm">
<div class="progress mb-0 rounded-0 rounded-top" style="height: 22px">
<div
class="progress mb-0 rounded-0 rounded-top"
style="height: 22px"
>
<div
class="progress-bar progress-bar-striped bg-primary force-gpu"
id="noise_level"
@ -90,10 +86,13 @@ function startStopRecordAudio(){
class="justify-content-center d-flex position-absolute w-100"
id="noise_level_value"
>
S-Meter(dB): {{state.s_meter_strength_raw}}
S-Meter(dB): {{ state.s_meter_strength_raw }}
</p>
</div>
<div class="progress mb-0 rounded-0 rounded-bottom" style="height: 8px">
<div
class="progress mb-0 rounded-0 rounded-bottom"
style="height: 8px"
>
<div
class="progress-bar progress-bar-striped bg-warning"
role="progressbar"
@ -129,7 +128,10 @@ function startStopRecordAudio(){
</div>
</div>
<div class="col-sm">
<div class="progress mb-0 rounded-0 rounded-top" style="height: 22px">
<div
class="progress mb-0 rounded-0 rounded-top"
style="height: 22px"
>
<div
class="progress-bar progress-bar-striped bg-primary force-gpu"
id="dbfs_level"
@ -143,10 +145,13 @@ function startStopRecordAudio(){
class="justify-content-center d-flex position-absolute w-100"
id="dbfs_level_value"
>
{{state.dbfs_level}} dBFS
{{ state.dbfs_level }} dBFS
</p>
</div>
<div class="progress mb-0 rounded-0 rounded-bottom" style="height: 8px">
<div
class="progress mb-0 rounded-0 rounded-bottom"
style="height: 8px"
>
<div
class="progress-bar progress-bar-striped bg-warning"
role="progressbar"

View file

@ -1,49 +1,42 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import {sendCQ, sendPing, startBeacon, stopBeacon} from '../js/sock.js'
import { sendCQ, sendPing, startBeacon, stopBeacon } from "../js/sock.js";
function transmitCQ(){
sendCQ()
function transmitCQ() {
sendCQ();
}
function transmitPing(){
sendPing(document.getElementById("dxCall").value)
function transmitPing() {
sendPing(document.getElementById("dxCall").value);
}
function startStopBeacon(){
function startStopBeacon() {
switch (state.beacon_state) {
case 'False':
startBeacon(settings.beacon_interval)
case "False":
startBeacon(settings.beacon_interval);
break;
case 'True':
stopBeacon()
case "True":
stopBeacon();
break;
default:
}
}
</script>
<template>
<div class="card mb-1">
<div class="card mb-1">
<div class="card-header p-1">
<div class="container">
<div class="row">
@ -61,10 +54,7 @@ function startStopBeacon(){
data-bs-target="#broadcastsHelpModal"
class="btn m-0 p-0 border-0"
>
<i
class="bi bi-question-circle"
style="font-size: 1rem"
></i>
<i class="bi bi-question-circle" style="font-size: 1rem"></i>
</button>
</div>
</div>
@ -99,7 +89,6 @@ function startStopBeacon(){
Ping
</button>
<button
class="btn btn-sm btn-outline-secondary ms-1"
id="sendCQ"
@ -115,8 +104,10 @@ function startStopBeacon(){
id="startBeacon"
class="btn btn-sm ms-1"
@click="startStopBeacon()"
v-bind:class="{ 'btn-success' : state.beacon_state === 'True',
'btn-outline-secondary' : state.beacon_state === 'False'}"
v-bind:class="{
'btn-success': state.beacon_state === 'True',
'btn-outline-secondary': state.beacon_state === 'False',
}"
title="Toggle beacon mode. The interval can be set in settings. While sending a beacon, you can receive ping requests and open a datachannel. If a datachannel is opened, the beacon pauses."
>
<i class="bi bi-soundwave"></i> Toggle beacon

View file

@ -1,5 +1,4 @@
<script setup lang="ts">
const {
locatorToLatLng,
distance,
@ -7,22 +6,19 @@ const {
latLngToLocator,
} = require("qth-locator");
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
function getDateTime(timestampRaw){
function getDateTime(timestampRaw) {
var datetime = new Date(timestampRaw * 1000).toLocaleString(
navigator.language,
{
@ -35,33 +31,25 @@ function getDateTime(timestampRaw){
second: "2-digit",
},
);
return datetime
return datetime;
}
function getMaidenheadDistance(dxGrid){
try{
function getMaidenheadDistance(dxGrid) {
try {
return parseInt(distance(settings.mygrid, dxGrid));
}catch(e){
//
} catch (e) {
//
}
}
}
</script>
<template>
<div class="card mb-1" style="height: 240px">
<div class="card mb-1" style="height: 240px">
<!--325px-->
<div class="card-header p-1">
<div class="container">
<div class="row">
<div class="col-auto">
<i
class="bi bi-list-columns-reverse"
style="font-size: 1.2rem"
></i>
<i class="bi bi-list-columns-reverse" style="font-size: 1.2rem"></i>
</div>
<div class="col-10">
<strong class="fs-5">Heard stations</strong>
@ -74,10 +62,7 @@ try{
data-bs-target="#heardStationsHelpModal"
class="btn m-0 p-0 border-0"
>
<i
class="bi bi-question-circle"
style="font-size: 1rem"
></i>
<i class="bi bi-question-circle" style="font-size: 1rem"></i>
</button>
</div>
</div>
@ -108,9 +93,11 @@ try{
<td>{{ getDateTime(item.timestamp) }}</td>
<td>{{ item.frequency }}</td>
<td>&nbsp;</td>
<td><span class="badge bg-secondary">{{ item.dxcallsign }}</span></td>
<td>
<span class="badge bg-secondary">{{ item.dxcallsign }}</span>
</td>
<td>{{ item.dxgrid }}</td>
<td>{{ getMaidenheadDistance(item.dxgrid)}} km</td>
<td>{{ getMaidenheadDistance(item.dxgrid) }} km</td>
<td>{{ item.datatype }}</td>
<td>{{ item.snr }}</td>
<!--<td>{{ item.offset }}</td>-->
@ -121,5 +108,4 @@ try{
<!-- END OF HEARD STATIONS TABLE -->
</div>
</div>
</template>

View file

@ -1,50 +1,51 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import {set_frequency, set_mode} from '../js/sock.js'
import { set_frequency, set_mode } from "../js/sock.js";
function set_hamlib_frequency(){
set_frequency(state.new_frequency)
function set_hamlib_frequency() {
set_frequency(state.new_frequency);
}
function set_hamlib_mode(){
set_mode(state.mode)
function set_hamlib_mode() {
set_mode(state.mode);
}
function set_hamlib_rf_level(){
set_rf_level(state.rf_level)
function set_hamlib_rf_level() {
set_rf_level(state.rf_level);
}
</script>
<template>
<div class=" mb-3">
<div class="mb-3">
<div class="card mb-1">
<div class="card-header p-1">
<div class="container">
<div class="row">
<div class="col-1">
<i class="bi bi-house-door" style="font-size: 1.2rem"></i>
</div>
<div class="col-10">
<strong class="fs-5 me-2">Radio control</strong> <span class="badge" v-bind:class="{ 'text-bg-success' : state.hamlib_status === 'connected',
'text-bg-danger disabled' : state.hamlib_status === 'disconnected'}">{{state.hamlib_status}}</span>
<strong class="fs-5 me-2">Radio control</strong>
<span
class="badge"
v-bind:class="{
'text-bg-success': state.hamlib_status === 'connected',
'text-bg-danger disabled':
state.hamlib_status === 'disconnected',
}"
>{{ state.hamlib_status }}</span
>
</div>
<div class="col-1 text-end">
<button
@ -55,36 +56,30 @@ function set_hamlib_rf_level(){
class="btn m-0 p-0 border-0"
disabled
>
<i
class="bi bi-question-circle"
style="font-size: 1rem"
></i>
<i class="bi bi-question-circle" style="font-size: 1rem"></i>
</button>
</div>
</div>
</div>
</div>
<div class="card-body p-2">
<div class="input-group bottom-0 m-0">
<div class="me-2">
<div class="input-group">
<span class="input-group-text">QRG</span>
<span class="input-group-text">{{state.frequency}} Hz</span>
<span class="input-group-text">{{ state.frequency }} Hz</span>
<span class="input-group-text">QSY</span>
<input type="text" class="form-control" v-model="state.new_frequency" style="max-width: 8rem;"
pattern="[0-9]*" list="frequencyDataList" v-bind:class="{ 'disabled' : state.hamlib_status === 'disconnected'}">
<input
type="text"
class="form-control"
v-model="state.new_frequency"
style="max-width: 8rem"
pattern="[0-9]*"
list="frequencyDataList"
v-bind:class="{
disabled: state.hamlib_status === 'disconnected',
}"
/>
<datalist id="frequencyDataList">
<option selected value="7053000">40m | USB | EU, US</option>
@ -95,30 +90,49 @@ function set_hamlib_rf_level(){
<option value="50308000">6m | USB | US</option>
<option value="50616000">6m | USB | EU, US</option>
</datalist>
<button class="btn btn-sm btn-outline-success" type="button" @click="set_hamlib_frequency" v-bind:class="{ 'disabled' : state.hamlib_status === 'disconnected'}">Apply</button>
<button
class="btn btn-sm btn-outline-success"
type="button"
@click="set_hamlib_frequency"
v-bind:class="{
disabled: state.hamlib_status === 'disconnected',
}"
>
Apply
</button>
</div>
</div>
</div>
<div class="me-2">
<div class="input-group">
<span class="input-group-text" >Mode</span>
<select class="form-control" v-model="state.mode" @click="set_hamlib_mode()" v-bind:class="{ 'disabled' : state.hamlib_status === 'disconnected'}">
<span class="input-group-text">Mode</span>
<select
class="form-control"
v-model="state.mode"
@click="set_hamlib_mode()"
v-bind:class="{
disabled: state.hamlib_status === 'disconnected',
}"
>
<option value="USB">USB</option>
<option value="LSB">LSB</option>
<option value="AM">AM</option>
<option value="FM">FM</option>
</select>
</select>
</div>
</div>
</div>
<div class="me-2">
<div class="input-group">
<span class="input-group-text" >Power</span>
<select class="form-control" v-model="state.rf_level" @click="set_hamlib_rf_level()" v-bind:class="{ 'disabled' : state.hamlib_status === 'disconnected'}">
<span class="input-group-text">Power</span>
<select
class="form-control"
v-model="state.rf_level"
@click="set_hamlib_rf_level()"
v-bind:class="{
disabled: state.hamlib_status === 'disconnected',
}"
>
<option value="0">-</option>
<option value="10">10</option>
<option value="20">20</option>
@ -131,45 +145,11 @@ function set_hamlib_rf_level(){
<option value="90">90</option>
<option value="100">100</option>
</select>
<span class="input-group-text" >%</span>
<span class="input-group-text">%</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div></div>
</template>

View file

@ -1,19 +1,16 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler';
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import {
Chart as ChartJS,
CategoryScale,
@ -22,42 +19,31 @@ import {
LineElement,
Title,
Tooltip,
Legend
} from 'chart.js'
import { Line, Scatter } from 'vue-chartjs'
import { ref, computed } from 'vue';
Legend,
} from "chart.js";
import { Line, Scatter } from "vue-chartjs";
import { ref, computed } from "vue";
function selectStatsControl(obj){
switch (obj.delegateTarget.id) {
case 'list-waterfall-list':
settings.spectrum = "waterfall"
function selectStatsControl(obj) {
switch (obj.delegateTarget.id) {
case "list-waterfall-list":
settings.spectrum = "waterfall";
break;
case 'list-scatter-list':
settings.spectrum = "scatter"
case "list-scatter-list":
settings.spectrum = "scatter";
break;
case 'list-chart-list':
settings.spectrum = "chart"
case "list-chart-list":
settings.spectrum = "chart";
break;
default:
settings.spectrum = "waterfall"
}
saveSettingsToFile()
settings.spectrum = "waterfall";
}
saveSettingsToFile();
}
var transmissionSpeedChartOptions = {
var transmissionSpeedChartOptions = {
type: "line",
};
};
ChartJS.register(
CategoryScale,
@ -66,17 +52,16 @@ ChartJS.register(
LineElement,
Title,
Tooltip,
Legend
)
Legend,
);
// https://www.chartjs.org/docs/latest/samples/line/segments.html
const skipped = (speedCtx, value) =>
const skipped = (speedCtx, value) =>
speedCtx.p0.skip || speedCtx.p1.skip ? value : undefined;
const down = (speedCtx, value) =>
const down = (speedCtx, value) =>
speedCtx.p0.parsed.y > speedCtx.p1.parsed.y ? value : undefined;
var transmissionSpeedChartOptions = {
var transmissionSpeedChartOptions = {
responsive: true,
animations: true,
cubicInterpolationMode: "monotone",
@ -97,7 +82,7 @@ ChartJS.register(
},
x: { ticks: { beginAtZero: true } },
},
};
};
const transmissionSpeedChartData = computed(() => ({
labels: state.arq_speed_list_timestamp,
@ -128,19 +113,16 @@ const transmissionSpeedChartData = computed(() => ({
order: 0,
yAxisID: "SPEED",
},
]
}
));
],
}));
const scatterChartOptions = {
responsive: true,
maintainAspectRatio: true,
scales: {
x: {
type: 'linear',
position: 'bottom',
type: "linear",
position: "bottom",
grid: {
display: true,
lineWidth: 1, // Set the line width for x-axis grid lines
@ -150,8 +132,8 @@ const scatterChartOptions = {
},
},
y: {
type: 'linear',
position: 'left',
type: "linear",
position: "left",
grid: {
display: true,
lineWidth: 1, // Set the line width for y-axis grid lines
@ -171,16 +153,21 @@ const scatterChartOptions = {
},
};
// dummy data
//state.scatter = [{"x":"166","y":"46"},{"x":"-193","y":"-139"},{"x":"-165","y":"-291"},{"x":"311","y":"-367"},{"x":"389","y":"199"},{"x":"78","y":"372"},{"x":"242","y":"-431"},{"x":"-271","y":"-248"},{"x":"28","y":"-130"},{"x":"-20","y":"187"},{"x":"74","y":"362"},{"x":"-316","y":"-229"},{"x":"-180","y":"261"},{"x":"321","y":"360"},{"x":"438","y":"-288"},{"x":"378","y":"-94"},{"x":"462","y":"-163"},{"x":"-265","y":"248"},{"x":"210","y":"314"},{"x":"230","y":"-320"},{"x":"261","y":"-244"},{"x":"-283","y":"-373"}]
const scatterChartData = computed(() => ({
datasets: [
{ type: 'scatter', fill: true, data: state.scatter, label: 'Scatter' ,tension: 0.1, borderColor: 'rgb(0, 255, 0)' },
]
}
));
{
type: "scatter",
fill: true,
data: state.scatter,
label: "Scatter",
tension: 0.1,
borderColor: "rgb(0, 255, 0)",
},
],
}));
</script>
<template>
@ -202,7 +189,7 @@ const scatterChartData = computed(() => ({
href="#list-waterfall"
role="tab"
aria-controls="list-waterfall"
v-bind:class="{ 'active' : settings.spectrum === 'waterfall'}"
v-bind:class="{ active: settings.spectrum === 'waterfall' }"
@click="selectStatsControl($event)"
><strong><i class="bi bi-water"></i></strong
></a>
@ -213,7 +200,7 @@ const scatterChartData = computed(() => ({
href="#list-scatter"
role="tab"
aria-controls="list-scatter"
v-bind:class="{ 'active' : settings.spectrum === 'scatter'}"
v-bind:class="{ active: settings.spectrum === 'scatter' }"
@click="selectStatsControl($event)"
><strong><i class="bi bi-border-outer"></i></strong
></a>
@ -224,7 +211,7 @@ const scatterChartData = computed(() => ({
href="#list-chart"
role="tab"
aria-controls="list-chart"
v-bind:class="{ 'active' : settings.spectrum === 'chart'}"
v-bind:class="{ active: settings.spectrum === 'chart' }"
@click="selectStatsControl($event)"
><strong><i class="bi bi-graph-up-arrow"></i></strong
></a>
@ -238,7 +225,10 @@ const scatterChartData = computed(() => ({
data-bs-toggle="tooltip"
data-bs-trigger="hover"
data-bs-html="true"
v-bind:class="{ 'btn-warning' : state.channel_busy === 'True', 'btn-outline-secondary' : state.channel_busy === 'False'}"
v-bind:class="{
'btn-warning': state.channel_busy === 'True',
'btn-outline-secondary': state.channel_busy === 'False',
}"
title="Channel busy state: <strong class='text-success'>not busy</strong> / <strong class='text-danger'>busy </strong>"
>
busy
@ -251,7 +241,10 @@ const scatterChartData = computed(() => ({
data-bs-trigger="hover"
data-bs-html="true"
title="Recieving data: illuminates <strong class='text-success'>green</strong> if receiving codec2 data"
v-bind:class="{ 'btn-success' : state.is_codec2_traffic === 'True', 'btn-outline-secondary' : state.is_codec2_traffic === 'False'}"
v-bind:class="{
'btn-success': state.is_codec2_traffic === 'True',
'btn-outline-secondary': state.is_codec2_traffic === 'False',
}"
>
signal
</button>
@ -276,7 +269,7 @@ const scatterChartData = computed(() => ({
<div class="tab-content" id="nav-stats-tabContent">
<div
class="tab-pane fade"
v-bind:class="{ 'show active' : settings.spectrum === 'waterfall'}"
v-bind:class="{ 'show active': settings.spectrum === 'waterfall' }"
id="list-waterfall"
role="stats_tabpanel"
aria-labelledby="list-waterfall-list"
@ -289,17 +282,16 @@ const scatterChartData = computed(() => ({
</div>
<div
class="tab-pane fade"
v-bind:class="{ 'show active' : settings.spectrum === 'scatter'}"
v-bind:class="{ 'show active': settings.spectrum === 'scatter' }"
id="list-scatter"
role="tabpanel"
aria-labelledby="list-scatter-list"
>
<Scatter :data="scatterChartData" :options="scatterChartOptions" />
</div>
<div
class="tab-pane fade"
v-bind:class="{ 'show active' : settings.spectrum === 'chart'}"
v-bind:class="{ 'show active': settings.spectrum === 'chart' }"
id="list-chart"
role="tabpanel"
aria-labelledby="list-chart-list"

View file

@ -1,20 +1,13 @@
<script setup>
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useAudioStore } from '../store/audioStore.js';
import { useAudioStore } from "../store/audioStore.js";
const audio = useAudioStore(pinia);
</script>
<template>
<div class="card mb-0">
<div class="card-header p-1">
<div class="container">
@ -33,10 +26,7 @@ const audio = useAudioStore(pinia);
data-bs-target="#audioHelpModal"
class="btn m-0 p-0 border-0"
>
<i
class="bi bi-question-circle"
style="font-size: 1rem"
></i>
<i class="bi bi-question-circle" style="font-size: 1rem"></i>
</button>
</div>
</div>
@ -53,8 +43,7 @@ const audio = useAudioStore(pinia);
id="audio_input_selectbox"
aria-label=".form-select-sm"
v-html="audio.getInputDevices()"
>
</select>
></select>
</div>
<div class="input-group input-group-sm">
<span class="input-group-text">
@ -65,8 +54,7 @@ const audio = useAudioStore(pinia);
id="audio_output_selectbox"
aria-label=".form-select-sm"
v-html="audio.getOutputDevices()"
>
</select>
></select>
</div>
</div>
</div>

View file

@ -1,18 +1,15 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
</script>
<template>
@ -20,13 +17,15 @@ const settings = useSettingsStore(pinia);
class="navbar fixed-bottom navbar-expand-xl bg-body-tertiary border-top p-2"
style="margin-left: 87px"
>
<div class="col">
<div class="btn-toolbar" role="toolbar" style="margin-left: 2px">
<div class="btn-group btn-group-sm me-1" role="group">
<button
class="btn btn-sm btn-secondary me-1"
v-bind:class="{ 'bg-danger' : state.ptt_state === 'True', 'bg-success' : state.ptt_state === 'False'}"
v-bind:class="{
'bg-danger': state.ptt_state === 'True',
'bg-success': state.ptt_state === 'False',
}"
id="ptt_state"
type="button"
data-bs-placement="top"
@ -46,7 +45,10 @@ const settings = useSettingsStore(pinia);
data-bs-toggle="tooltip"
data-bs-trigger="hover"
data-bs-html="true"
v-bind:class="{ 'bg-danger' : state.busy_state === 'BUSY', 'bg-success' : state.busy_state === 'IDLE'}"
v-bind:class="{
'bg-danger': state.busy_state === 'BUSY',
'bg-success': state.busy_state === 'IDLE',
}"
title="TNC busy state: <strong class='text-success'>IDLE</strong> / <strong class='text-danger'>BUSY</strong>"
>
<i class="bi bi-cpu" style="font-size: 0.8rem"></i>
@ -61,7 +63,10 @@ const settings = useSettingsStore(pinia);
data-bs-trigger="hover"
data-bs-html="true"
title="ARQ SESSION state: <strong class='text-warning'>OPEN</strong>"
v-bind:class="{ 'bg-secondary' : state.arq_session_state === 'disconnected', 'bg-success' : state.arq_session_state === 'connected'}"
v-bind:class="{
'bg-secondary': state.arq_session_state === 'disconnected',
'bg-success': state.arq_session_state === 'connected',
}"
>
<i class="bi bi-arrow-left-right" style="font-size: 0.8rem"></i>
</button>
@ -75,15 +80,14 @@ const settings = useSettingsStore(pinia);
data-bs-trigger="hover"
data-bs-html="true"
title="DATA-CHANNEL state: <strong class='text-warning'>OPEN</strong>"
v-bind:class="{ 'bg-secondary' : state.arq_state === 'False', 'bg-success' : state.arq_state === 'True'}"
v-bind:class="{
'bg-secondary': state.arq_state === 'False',
'bg-success': state.arq_state === 'True',
}"
>
<i
class="bi bi-file-earmark-binary"
style="font-size: 0.8rem"
></i>
<i class="bi bi-file-earmark-binary" style="font-size: 0.8rem"></i>
</button>
<!--
<!--
<button
class="btn btn-sm btn-secondary me-1"
id="rigctld_state"
@ -98,24 +102,23 @@ const settings = useSettingsStore(pinia);
</button>
-->
<button
<button
class="btn btn-sm disabled me-3"
type="button"
data-bs-placement="top"
data-bs-toggle="tooltip"
data-bs-trigger="hover"
data-bs-html="true"
v-bind:class="{ 'btn-warning' : state.channel_busy === 'True', 'btn-secondary' : state.channel_busy === 'False'}"
v-bind:class="{
'btn-warning': state.channel_busy === 'True',
'btn-secondary': state.channel_busy === 'False',
}"
title="Channel busy state: <strong class='text-success'>not busy</strong> / <strong class='text-danger'>busy </strong>"
>
<i class="bi bi-hourglass"></i>
</button>
</div>
<div class="btn-group btn-group-sm me-1" role="group">
<button
class="btn btn-sm btn-secondary me-4 disabled"
@ -125,19 +128,11 @@ const settings = useSettingsStore(pinia);
data-bs-trigger="hover"
data-bs-html="true"
>
{{state.frequency}} Hz
{{ state.frequency }} Hz
</button>
</div>
<div class="btn-group btn-group-sm me-1" role="group">
<button
class="btn btn-sm btn-secondary me-0"
type="button"
@ -149,7 +144,6 @@ const settings = useSettingsStore(pinia);
<i class="bi bi-speedometer2" style="font-size: 1rem"></i>
</button>
<button
class="btn btn-sm btn-secondary me-4 disabled"
type="button"
@ -158,25 +152,20 @@ const settings = useSettingsStore(pinia);
data-bs-trigger="hover"
data-bs-html="true"
>
<i class="bi " style="font-size: 1rem"
v-bind:class="{ 'bi-reception-0' : state.speed_level === '0',
'bi-reception-1' : state.speed_level === '1',
'bi-reception-2' : state.speed_level === '2',
'bi-reception-3' : state.speed_level === '3',
'bi-reception-4' : state.speed_level === '4',
<i
class="bi"
style="font-size: 1rem"
v-bind:class="{
'bi-reception-0': state.speed_level === '0',
'bi-reception-1': state.speed_level === '1',
'bi-reception-2': state.speed_level === '2',
'bi-reception-3': state.speed_level === '3',
'bi-reception-4': state.speed_level === '4',
}"
></i>
</button>
</div>
</div>
<div class="btn-group btn-group-sm me-1" role="group">
<button
class="btn btn-sm btn-secondary me-0"
type="button"
@ -188,7 +177,6 @@ const settings = useSettingsStore(pinia);
<i class="bi bi-file-earmark-binary" style="font-size: 1rem"></i>
</button>
<button
class="btn btn-sm btn-secondary me-4 disabled"
type="button"
@ -197,9 +185,9 @@ const settings = useSettingsStore(pinia);
data-bs-trigger="hover"
data-bs-html="true"
>
{{state.arq_total_bytes}}
{{ state.arq_total_bytes }}
</button>
</div>
</div>
<div class="btn-group btn-group-sm me-1" role="group">
<button
class="btn btn-sm btn-secondary me-0"
@ -212,7 +200,6 @@ const settings = useSettingsStore(pinia);
<i class="bi bi-file-earmark-binary" style="font-size: 1rem"></i>
</button>
<button
class="btn btn-sm btn-secondary disabled me-1"
type="button"
@ -221,24 +208,17 @@ const settings = useSettingsStore(pinia);
data-bs-trigger="hover"
data-bs-html="true"
>
{{state.dxcallsign}}
{{ state.dxcallsign }}
</button>
</div>
</div>
</div>
<div class="col-lg-4">
<div style="margin-right: 2px">
<div class="progress w-100 rounded-0 rounded-top" style="height: 20px; min-width: 200px">
<div
class="progress w-100 rounded-0 rounded-top"
style="height: 20px; min-width: 200px"
>
<div
class="progress-bar progress-bar-striped bg-primary force-gpu"
id="transmission_progress"
@ -248,16 +228,15 @@ const settings = useSettingsStore(pinia);
aria-valuemin="0"
aria-valuemax="100"
></div>
<p
class="justify-content-center m-0 d-flex position-absolute w-100"
>
{{state.arq_seconds_until_finish}}s left
<p class="justify-content-center m-0 d-flex position-absolute w-100">
{{ state.arq_seconds_until_finish }}s left
</p>
</div>
<div class="progress mb-0 rounded-0 rounded-bottom" style="height: 10px">
<div
class="progress mb-0 rounded-0 rounded-bottom"
style="height: 10px"
>
<div
class="progress-bar progress-bar-striped bg-warning"
id="transmission_timeleft"
@ -267,21 +246,14 @@ const settings = useSettingsStore(pinia);
aria-valuemin="0"
aria-valuemax="100"
>
<p
class="justify-content-center m-0 d-flex position-absolute w-100"
>
timeout in: {{state.arq_seconds_until_timeout}}s
timeout in: {{ state.arq_seconds_until_timeout }}s
</p>
</div>
</div>
</div>
</div>
</nav>
</template>

View file

@ -1,35 +1,29 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import {sendTestFrame, setTxAudioLevel} from '../js/sock.js'
import { sendTestFrame, setTxAudioLevel } from "../js/sock.js";
function tuneAudio(){
sendTestFrame()
function tuneAudio() {
sendTestFrame();
}
function set_audio_level(obj){
setTxAudioLevel(state.audio_level)
function set_audio_level(obj) {
setTxAudioLevel(state.audio_level);
}
</script>
<template>
<!-- HELP MODALS AUDIO -->
<!-- HELP MODALS AUDIO -->
<div
class="modal fade"
data-bs-backdrop="static"
@ -127,8 +121,8 @@ setTxAudioLevel(state.audio_level)
<div class="card-body">
<h5 class="card-title">None/Vox</h5>
<p class="card-text">
Select "None/Vox" if you want to use Vox for triggering PTT.
No connection to rigctld will be established. No frequency
Select "None/Vox" if you want to use Vox for triggering PTT. No
connection to rigctld will be established. No frequency
information is availble.
</p>
</div>
@ -140,8 +134,8 @@ setTxAudioLevel(state.audio_level)
<p class="card-text">
Select "Hamlib" if you want to have more control over your
radio. Define your hamlib settings in settings, and click the
start button to start rigctld. You may use the 'PTT test'
button to ensure rig control is working.
start button to start rigctld. You may use the 'PTT test' button
to ensure rig control is working.
</p>
</div>
</div>
@ -243,8 +237,8 @@ setTxAudioLevel(state.audio_level)
</div>
</h5>
<p class="card-text">
Enter your position as a 4 or 6 digit grid square, also known
as a maidenhead locator. Six digits are recommended.
Enter your position as a 4 or 6 digit grid square, also known as
a maidenhead locator. Six digits are recommended.
</p>
</div>
</div>
@ -276,8 +270,8 @@ setTxAudioLevel(state.audio_level)
<h5 class="card-title">Auto-Updater</h5>
<p class="card-text">
The auto updater loads the latest version from Github and
installs it automatically. You can select the update channel
in settings. Once an update has been downlaoded, you need to
installs it automatically. You can select the update channel in
settings. Once an update has been downlaoded, you need to
confirm the auto-installation and restart.
</p>
</div>
@ -297,8 +291,7 @@ setTxAudioLevel(state.audio_level)
<p class="card-text">
Beta releases are more stable than Alpha releases. They are a
good tradeoff between latest features and stability. They will
be updated less often. A beta release has not been released
yet.
be updated less often. A beta release has not been released yet.
</p>
</div>
</div>
@ -306,8 +299,8 @@ setTxAudioLevel(state.audio_level)
<div class="card-body">
<h5 class="card-title">Stable</h5>
<p class="card-text">
Stable releases are the most stable versions with no known
major issues. A stable release has not been released yet.
Stable releases are the most stable versions with no known major
issues. A stable release has not been released yet.
</p>
</div>
</div>
@ -415,11 +408,7 @@ setTxAudioLevel(state.audio_level)
aria-describedby="basic-addon1"
disabled
/>
<button
class="btn btn-sm btn-danger"
type="button"
disabled
>
<button class="btn btn-sm btn-danger" type="button" disabled>
<i class="bi bi-diagram-3" style="font-size: 1rem"></i>
</button>
</div>
@ -567,8 +556,8 @@ setTxAudioLevel(state.audio_level)
</div>
</h5>
<p class="card-text">
Represents the level of audio from transceiver. Excessively
high levels will affect decoding performance negatively.
Represents the level of audio from transceiver. Excessively high
levels will affect decoding performance negatively.
</p>
</div>
</div>
@ -635,17 +624,14 @@ setTxAudioLevel(state.audio_level)
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title">
<button
type="button"
class="btn btn-sm btn-outline-secondary"
>
<button type="button" class="btn btn-sm btn-outline-secondary">
Tune
</button>
</h5>
<p class="card-text">
Adjust volume level of outgoing audio to transceiver. For best
results lower the level so that a minimum amount of ALC is
used. Can be used in combination with rig's mic/input gain for
results lower the level so that a minimum amount of ALC is used.
Can be used in combination with rig's mic/input gain for
furthrer refinement.
</p>
</div>
@ -694,12 +680,11 @@ setTxAudioLevel(state.audio_level)
</button>
<p class="card-text">
Send a ping to a remote station by entering a callsign and
optional SSID (-0 will be used if not specified.)
Alternatively click on a station in the heard station list to
populate the call sign field. If the remote station decodes
the ping it will transmit a reply. If able to decode the
reply, a signal report will be listed in the heard station
list.
optional SSID (-0 will be used if not specified.) Alternatively
click on a station in the heard station list to populate the
call sign field. If the remote station decodes the ping it will
transmit a reply. If able to decode the reply, a signal report
will be listed in the heard station list.
</p>
</div>
</div>
@ -787,8 +772,8 @@ setTxAudioLevel(state.audio_level)
</button>
</h5>
<p class="card-text">
Green when channel is open and changes to red to indicate
there is activity on the channel.
Green when channel is open and changes to red to indicate there
is activity on the channel.
</p>
</div>
</div>
@ -815,8 +800,8 @@ setTxAudioLevel(state.audio_level)
</label>
</h5>
<p class="card-text">
Displays a plot of last decoded message. A constellation plot
is a simple way to represent signal quality.
Displays a plot of last decoded message. A constellation plot is
a simple way to represent signal quality.
</p>
</div>
</div>
@ -864,9 +849,9 @@ setTxAudioLevel(state.audio_level)
<p class="card-text">
Stations that you've been able to decode will be listed here.
Details such as time, frequency, message type, call sign,
location and SNR will be listed. Existing entries are updated
if they already exist and more detailed history can be viewed
in chat window for each station.
location and SNR will be listed. Existing entries are updated if
they already exist and more detailed history can be viewed in
chat window for each station.
</p>
</div>
</div>
@ -896,13 +881,18 @@ setTxAudioLevel(state.audio_level)
<div class="modal-body">
<div class="input-group input-group-sm mb-1">
<span class="input-group-text">Test-Frame</span>
<button type="button" id="sendTestFrame" @click="sendTestFrame()" class="btn btn-danger">
<button
type="button"
id="sendTestFrame"
@click="sendTestFrame()"
class="btn btn-danger"
>
Transmit
</button>
</div>
<div class="input-group input-group-sm mb-1">
<span class="input-group-text">TX Level</span>
<span class="input-group-text" >{{state.audio_level}}</span>
<span class="input-group-text">{{ state.audio_level }}</span>
<span class="input-group-text w-75">
<input
type="range"
@ -919,5 +909,4 @@ setTxAudioLevel(state.audio_level)
</div>
</div>
</div>
</template>
</template>

View file

@ -1,24 +1,20 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
function saveSettings(){
saveSettingsToFile()
function saveSettings() {
saveSettingsToFile();
}
</script>
<template>
<div class="card mb-1">
<div class="card mb-1">
<div class="card-header p-1">
<div class="container">
<div class="row">
@ -36,10 +32,7 @@ function saveSettings(){
data-bs-target="#stationHelpModal"
class="btn m-0 p-0 border-0"
>
<i
class="bi bi-question-circle"
style="font-size: 1rem"
></i>
<i class="bi bi-question-circle" style="font-size: 1rem"></i>
</button>
</div>
</div>
@ -57,10 +50,7 @@ function saveSettings(){
title="Enter your callsign and save it"
>
<span class="input-group-text">
<i
class="bi bi-person-bounding-box"
style="font-size: 1rem"
></i>
<i class="bi bi-person-bounding-box" style="font-size: 1rem"></i>
</span>
<input
type="text"

View file

@ -1,41 +1,34 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
function selectRadioControl(obj){
switch (event.target.id) {
case 'list-rig-control-none-list':
settings.radiocontrol = "disabled"
function selectRadioControl(obj) {
switch (event.target.id) {
case "list-rig-control-none-list":
settings.radiocontrol = "disabled";
break;
case 'list-rig-control-rigctld-list':
settings.radiocontrol = "rigctld"
case "list-rig-control-rigctld-list":
settings.radiocontrol = "rigctld";
break;
case 'list-rig-control-tci-list':
settings.radiocontrol = "tci"
case "list-rig-control-tci-list":
settings.radiocontrol = "tci";
break;
default:
console.log("default=!==")
settings.radiocontrol = "disabled"
console.log("default=!==");
settings.radiocontrol = "disabled";
}
saveSettingsToFile();
}
saveSettingsToFile()
}
</script>
<template>
<div class="card mb-0">
<div class="card mb-0">
<div class="card-header p-1">
<div class="container">
<div class="row">
@ -46,18 +39,46 @@ switch (event.target.id) {
<strong class="fs-5">Rig control</strong>
</div>
<div class="col-6">
<div class="list-group list-group-horizontal" id="rig-control-list-tab" role="rig-control-tablist">
<a class="py-1 list-group-item list-group-item-action" id="list-rig-control-none-list" data-bs-toggle="list" href="#list-rig-control-none" role="tab" aria-controls="list-rig-control-none" v-bind:class="{ 'active' : settings.radiocontrol === 'disabled'}" @click="selectRadioControl()">None/Vox</a>
<a class="py-1 list-group-item list-group-item-action" id="list-rig-control-rigctld-list" data-bs-toggle="list" href="#list-rig-control-rigctld" role="tab" aria-controls="list-rig-control-rigctld" v-bind:class="{ 'active' : settings.radiocontrol === 'rigctld'}" @click="selectRadioControl()">Rigctld</a>
<a class="py-1 list-group-item list-group-item-action" id="list-rig-control-tci-list" data-bs-toggle="list" href="#list-rig-control-tci" role="tab" aria-controls="list-rig-control-tci" v-bind:class="{ 'active' : settings.radiocontrol === 'tci'}" @click="selectRadioControl()">TCI</a>
<div
class="list-group list-group-horizontal"
id="rig-control-list-tab"
role="rig-control-tablist"
>
<a
class="py-1 list-group-item list-group-item-action"
id="list-rig-control-none-list"
data-bs-toggle="list"
href="#list-rig-control-none"
role="tab"
aria-controls="list-rig-control-none"
v-bind:class="{ active: settings.radiocontrol === 'disabled' }"
@click="selectRadioControl()"
>None/Vox</a
>
<a
class="py-1 list-group-item list-group-item-action"
id="list-rig-control-rigctld-list"
data-bs-toggle="list"
href="#list-rig-control-rigctld"
role="tab"
aria-controls="list-rig-control-rigctld"
v-bind:class="{ active: settings.radiocontrol === 'rigctld' }"
@click="selectRadioControl()"
>Rigctld</a
>
<a
class="py-1 list-group-item list-group-item-action"
id="list-rig-control-tci-list"
data-bs-toggle="list"
href="#list-rig-control-tci"
role="tab"
aria-controls="list-rig-control-tci"
v-bind:class="{ active: settings.radiocontrol === 'tci' }"
@click="selectRadioControl()"
>TCI</a
>
</div>
</div>
<div class="col-1 text-end">
@ -68,25 +89,34 @@ switch (event.target.id) {
data-bs-target="#rigcontrolHelpModal"
class="btn m-0 p-0 border-0"
>
<i
class="bi bi-question-circle"
style="font-size: 1rem"
></i>
<i class="bi bi-question-circle" style="font-size: 1rem"></i>
</button>
</div>
</div>
</div>
</div>
<div class="card-body p-2" style="height: 100px">
<div class="tab-content" id="rig-control-nav-tabContent">
<div class="tab-pane fade" v-bind:class="{ 'show active' : settings.radiocontrol === 'disabled'}" id="list-rig-control-none" role="tabpanel" aria-labelledby="list-rig-control-none-list"><p class="small">
TNC will not utilize rig control and features will be
limited. While functional; it is recommended to configure
hamlib.
</p></div>
<div class="tab-pane fade" id="list-rig-control-rigctld" v-bind:class="{ 'show active' : settings.radiocontrol === 'rigctld'}" role="tabpanel" aria-labelledby="list-rig-control-rigctld-list"><div class="input-group input-group-sm mb-1">
<div
class="tab-pane fade"
v-bind:class="{ 'show active': settings.radiocontrol === 'disabled' }"
id="list-rig-control-none"
role="tabpanel"
aria-labelledby="list-rig-control-none-list"
>
<p class="small">
TNC will not utilize rig control and features will be limited. While
functional; it is recommended to configure hamlib.
</p>
</div>
<div
class="tab-pane fade"
id="list-rig-control-rigctld"
v-bind:class="{ 'show active': settings.radiocontrol === 'rigctld' }"
role="tabpanel"
aria-labelledby="list-rig-control-rigctld-list"
>
<div class="input-group input-group-sm mb-1">
<div class="input-group input-group-sm mb-1">
<span class="input-group-text">Rigctld</span>
<span class="input-group-text">Address</span>
@ -148,8 +178,16 @@ switch (event.target.id) {
PTT Test
</button>
</div>
</div></div>
<div class="tab-pane fade" id="list-rig-control-tci" v-bind:class="{ 'show active' : settings.radiocontrol === 'tci'}" role="tabpanel" aria-labelledby="list-rig-control-tci-list"><div class="input-group input-group-sm mb-1">
</div>
</div>
<div
class="tab-pane fade"
id="list-rig-control-tci"
v-bind:class="{ 'show active': settings.radiocontrol === 'tci' }"
role="tabpanel"
aria-labelledby="list-rig-control-tci-list"
>
<div class="input-group input-group-sm mb-1">
<div class="input-group input-group-sm mb-1">
<span class="input-group-text">TCI</span>
<span class="input-group-text">Address</span>
@ -174,27 +212,17 @@ switch (event.target.id) {
v-model="settings.tci_port"
/>
</div>
</div></div>
</div>
</div>
</div>
<!-- RADIO CONTROL DISABLED -->
<div id="radio-control-disabled">
</div>
<div id="radio-control-disabled"></div>
<!-- RADIO CONTROL RIGCTLD -->
<div id="radio-control-rigctld">
</div>
<div id="radio-control-rigctld"></div>
<!-- RADIO CONTROL TCI-->
<div id="radio-control-tci">
</div>
<div id="radio-control-tci"></div>
<!-- RADIO CONTROL HELP -->
<div id="radio-control-help">
<!--
@ -207,11 +235,10 @@ switch (event.target.id) {
happens automatically.
-->
</div>
</div>
<!--<div class="card-footer text-muted small" id="hamlib_info_field">
Define TNC rig control mode (none/hamlib)
</div>
-->
</div>
</template>
</template>

View file

@ -1,68 +1,54 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import {startTNC, stopTNC} from '../js/daemon.js'
function startStopTNC(){
switch (state.tnc_running_state) {
case 'stopped':
import { startTNC, stopTNC } from "../js/daemon.js";
function startStopTNC() {
switch (state.tnc_running_state) {
case "stopped":
// todo: is there another way of doing this, maybe more VueJS like?
settings.rx_audio = document.getElementById("audio_input_selectbox").value
settings.tx_audio = document.getElementById("audio_output_selectbox").value
settings.rx_audio = document.getElementById(
"audio_input_selectbox",
).value;
settings.tx_audio = document.getElementById(
"audio_output_selectbox",
).value;
startTNC()
startTNC();
break;
case 'running':
stopTNC()
case "running":
stopTNC();
break;
default:
}
}
}
</script>
<template>
<nav class="navbar bg-body-tertiary border-bottom">
<nav class="navbar bg-body-tertiary border-bottom">
<div class="mx-auto">
<span class="badge bg-secondary me-4"
>TNC location | {{ settings.tnc_host }}</span
>
<div class="btn-group" role="group">
<span class="badge bg-secondary me-4"
>Service | {{ state.tnc_running_state }}</span
>
<button
type="button"
id="startTNC"
class="btn btn-sm btn-outline-secondary disabled me-4"
>TNC address: {{settings.tnc_host}}
</button>
</div>
<div class="btn-group" role="group"></div>
<div class="btn-group me-4" role="group">
<button
type="button"
id="startTNC"
@ -72,10 +58,10 @@ switch (state.tnc_running_state) {
data-bs-html="false"
title="Start the TNC. Please set your audio and radio settings first!"
@click="startStopTNC()"
v-bind:class="{ 'disabled' : state.tnc_running_state === 'running'}"
v-bind:class="{ disabled: state.tnc_running_state === 'running' }"
>
<i class="bi bi-play-fill"></i>
<span class="ms-2">Start tnc</span>
<span class="ms-2">start tnc</span>
</button>
<button
type="button"
@ -86,27 +72,13 @@ switch (state.tnc_running_state) {
data-bs-html="false"
title="Stop the TNC."
@click="startStopTNC()"
v-bind:class="{ 'disabled' : state.tnc_running_state === 'stopped'}"
v-bind:class="{ disabled: state.tnc_running_state === 'stopped' }"
>
<i class="bi bi-stop-fill"></i>
<span class="ms-2">Stop tnc</span>
<span class="ms-2">stop tnc</span>
</button>
</div>
<div class="btn-group me-1" role="group">
<button
type="button"
id="startTNC"
class="btn btn-sm btn-outline-secondary disabled"
>TNC state:{{state.tnc_running_state}}
</button>
</div>
<button
type="button"
id="openHelpModalStartStopTNC"
@ -116,11 +88,8 @@ switch (state.tnc_running_state) {
>
<i class="bi bi-question-circle" style="font-size: 1rem"></i>
</button>
</div>
<!--
<div class="btn-toolbar" role="toolbar">
@ -142,6 +111,5 @@ switch (state.tnc_running_state) {
</span>
</div>
-->
</nav>
--></nav>
</template>

View file

@ -1,26 +1,19 @@
<script setup lang="ts">
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
</script>
<template>
<div class="card mb-0">
<div class="card mb-0">
<div class="card-header p-1 d-flex">
<div class="container">
<div class="row">
<div class="col-1">
<i
class="bi bi-cloud-download"
style="font-size: 1.2rem"
></i>
<i class="bi bi-cloud-download" style="font-size: 1.2rem"></i>
</div>
<div class="col-3">
<strong class="fs-5">Updater</strong>
@ -49,10 +42,7 @@ const settings = useSettingsStore(pinia);
data-bs-target="#updaterHelpModal"
class="btn m-0 p-0 border-0"
>
<i
class="bi bi-question-circle"
style="font-size: 1rem"
></i>
<i class="bi bi-question-circle" style="font-size: 1rem"></i>
</button>
</div>
</div>
@ -64,9 +54,8 @@ const settings = useSettingsStore(pinia);
id="updater_channel"
type="button"
disabled
>
{{settings.update_channel}}
{{ settings.update_channel }}
</button>
<button
class="btn btn-secondary btn-sm"
@ -94,4 +83,4 @@ const settings = useSettingsStore(pinia);
</button>
</div>
</div>
</template>
</template>

View file

@ -1,10 +1,10 @@
<script setup lang="ts">
import settings_gui from './settings_gui.vue'
import settings_chat from './settings_chat.vue'
import settings_hamlib from './settings_hamlib.vue'
import settings_tnc from './settings_tnc.vue'
import settings_web from './settings_web.vue'
import settings_exp from './settings_exp.vue'
import settings_gui from "./settings_gui.vue";
import settings_chat from "./settings_chat.vue";
import settings_hamlib from "./settings_hamlib.vue";
import settings_tnc from "./settings_tnc.vue";
import settings_web from "./settings_web.vue";
import settings_exp from "./settings_exp.vue";
</script>
<template>
<div

View file

@ -1,21 +1,19 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
function saveSettings(){
saveSettingsToFile()
function saveSettings() {
saveSettingsToFile();
}
</script>
<template>
<div class="input-group input-group-sm mb-1">
<label class="input-group-text w-50">Enable "is typing"</label>
<label class="input-group-text w-50">
@ -24,7 +22,10 @@ function saveSettings(){
class="form-check-input"
type="checkbox"
id="enable_is_writing"
@change="saveSettings" v-model="settings.enable_is_writing" true-value="True" false-value="False"
@change="saveSettings"
v-model="settings.enable_is_writing"
true-value="True"
false-value="False"
/>
<label class="form-check-label" for="GraphicsSwitch"
>Additional broadcast burst</label
@ -34,16 +35,17 @@ function saveSettings(){
</div>
<div class="input-group input-group-sm mb-1">
<label class="input-group-text w-50"
>Allow requesting "user profile"</label
>
<label class="input-group-text w-50">Allow requesting "user profile"</label>
<label class="input-group-text w-50">
<div class="form-check form-switch form-check-inline">
<input
class="form-check-input"
type="checkbox"
id="enable_request_profile"
@change="saveSettings" v-model="settings.enable_request_profile" true-value="True" false-value="False"
@change="saveSettings"
v-model="settings.enable_request_profile"
true-value="True"
false-value="False"
/>
</div>
</label>
@ -59,7 +61,10 @@ function saveSettings(){
class="form-check-input"
type="checkbox"
id="enable_request_shared_folder"
@change="saveSettings" v-model="settings.enable_request_shared_folder" true-value="True" false-value="False"
@change="saveSettings"
v-model="settings.enable_request_shared_folder"
true-value="True"
false-value="False"
/>
</div>
</label>
@ -67,8 +72,13 @@ function saveSettings(){
<div class="input-group input-group-sm mb-1">
<label class="input-group-text w-50">Shared folder path</label>
<input type="text" class="form-control w-50" id="shared_folder_path" @change="saveSettings"
v-model="settings.shared_folder_path" />
<input
type="text"
class="form-control w-50"
id="shared_folder_path"
@change="saveSettings"
v-model="settings.shared_folder_path"
/>
</div>
<div class="input-group input-group-sm mb-1">
@ -82,7 +92,10 @@ function saveSettings(){
class="form-check-input"
type="checkbox"
id="enable_auto_retry"
@change="saveSettings" v-model="settings.enable_auto_retry" true-value="True" false-value="False"
@change="saveSettings"
v-model="settings.enable_auto_retry"
true-value="True"
false-value="False"
/>
</div>
</label>
@ -90,8 +103,12 @@ function saveSettings(){
<div class="input-group input-group-sm mb-1">
<span class="input-group-text w-50">message retry attempts</span>
<select class="form-select form-select-sm w-50" id="max_retry_attempts" @change="saveSettings"
v-model="settings.max_retry_attempts">
<select
class="form-select form-select-sm w-50"
id="max_retry_attempts"
@change="saveSettings"
v-model="settings.max_retry_attempts"
>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>

View file

@ -1,27 +1,32 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
function saveSettings(){
saveSettingsToFile()
function saveSettings() {
saveSettingsToFile();
}
</script>
<template>
<div class="input-group input-group-sm mb-1">
<label class="input-group-text w-50">Enable autotune</label>
<label class="input-group-text w-50">
<div class="form-check form-switch form-check-inline ms-2">
<input class="form-check-input" type="checkbox" id="autoTuneSwitch" @change="saveSettings" v-model="settings.auto_tune" true-value="True" false-value="False" />
<input
class="form-check-input"
type="checkbox"
id="autoTuneSwitch"
@change="saveSettings"
v-model="settings.auto_tune"
true-value="True"
false-value="False"
/>
<label class="form-check-label" for="autoTuneSwitch"
>adjust ALC on TX</label
>
@ -32,7 +37,15 @@ function saveSettings(){
<label class="input-group-text w-50">Enable FSK mode</label>
<label class="input-group-text w-50">
<div class="form-check form-switch form-check-inline ms-2">
<input class="form-check-input" type="checkbox" id="fskModeSwitch" @change="saveSettings" v-model="settings.enable_fsk" true-value="True" false-value="False"/>
<input
class="form-check-input"
type="checkbox"
id="fskModeSwitch"
@change="saveSettings"
v-model="settings.enable_fsk"
true-value="True"
false-value="False"
/>
<label class="form-check-label" for="fskModeSwitch"
>not available, yet</label
>
@ -48,7 +61,9 @@ function saveSettings(){
type="checkbox"
id="enableMeshSwitch"
@change="saveSettings"
v-model="settings.enable_mesh_features" true-value="True" false-value="False"
v-model="settings.enable_mesh_features"
true-value="True"
false-value="False"
/>
<label class="form-check-label" for="enableMeshSwitch"
>experimental! REALLY!</label
@ -63,7 +78,6 @@ function saveSettings(){
class="btn btn-outline-secondary btn-sm w-50"
id="btnCleanDB"
type="button"
>
Clean</button
>&nbsp;

View file

@ -1,24 +1,18 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
function saveSettings(){
saveSettingsToFile()
function saveSettings() {
saveSettingsToFile();
}
</script>
<template>
<div class="input-group input-group-sm mb-1">
<span class="input-group-text w-50">GUI theme</span>
<select
@ -59,8 +53,12 @@ function saveSettings(){
</div>
<div class="input-group input-group-sm mb-1">
<span class="input-group-text w-50">Waterfall theme</span>
<select class="form-select form-select-sm w-50" id="wftheme_selector" @change="saveSettings"
v-model="settings.wftheme">
<select
class="form-select form-select-sm w-50"
id="wftheme_selector"
@change="saveSettings"
v-model="settings.wftheme"
>
<option value="2">Default</option>
<option value="0">Turbo</option>
<option value="1">Fosphor</option>
@ -74,7 +72,15 @@ function saveSettings(){
<label class="input-group-text w-50">Enable fancy GUI</label>
<label class="input-group-text w-50">
<div class="form-check form-switch form-check-inline">
<input class="form-check-input" type="checkbox" id="GraphicsSwitch" @change="saveSettings" v-model="settings.high_graphics" true-value="True" false-value="False"/>
<input
class="form-check-input"
type="checkbox"
id="GraphicsSwitch"
@change="saveSettings"
v-model="settings.high_graphics"
true-value="True"
false-value="False"
/>
<label class="form-check-label" for="GraphicsSwitch"
>Higher CPU Usage</label
>
@ -85,7 +91,7 @@ function saveSettings(){
<label class="input-group-text w-50" for="inputGroupFile02"
>Received files folder</label
>
<input type="text" class="form-control w-50" id="received_files_folder"/>
<input type="text" class="form-control w-50" id="received_files_folder" />
</div>
<div class="input-group input-group-sm mb-1">
<span class="input-group-text w-50">Update channel</span>
@ -108,7 +114,10 @@ function saveSettings(){
class="form-check-input"
type="checkbox"
id="NotificationSwitch"
@change="saveSettings" v-model="settings.enable_sys_notification" true-value="True" false-value="False"
@change="saveSettings"
v-model="settings.enable_sys_notification"
true-value="True"
false-value="False"
/>
<label class="form-check-label" for="NotificationSwitch"
>Show system pop-ups</label
@ -124,7 +133,10 @@ function saveSettings(){
class="form-check-input"
type="checkbox"
id="AutoStartSwitch"
@change="saveSettings" v-model="settings.auto_start" true-value="True" false-value="False"
@change="saveSettings"
v-model="settings.auto_start"
true-value="True"
false-value="False"
/>
<label class="form-check-label" for="AutoStartSwitch"
>Start on app launch</label
@ -132,5 +144,4 @@ function saveSettings(){
</div>
</label>
</div>
</template>

View file

@ -1,21 +1,18 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
function saveSettings(){
saveSettingsToFile()
function saveSettings() {
saveSettingsToFile();
}
</script>
<template>
<hr class="m-2" />
<div class="input-group input-group-sm mb-1">
<span class="input-group-text" style="width: 180px">Rigctld path</span>
@ -291,9 +288,7 @@ function saveSettings(){
<option value="24001">RFT EKD-500</option>
<option value="25001">Elektor Elektor 3/04</option>
<option value="25002">SAT-Schneider DRT1</option>
<option value="25003">
Coding Technologies Digital World Traveller
</option>
<option value="25003">Coding Technologies Digital World Traveller</option>
<option value="25006">AmQRP DDS-60</option>
<option value="25007">Elektor Elektor SDR-USB</option>
<option value="25008">mRS miniVNA</option>
@ -394,9 +389,7 @@ function saveSettings(){
</select>
</div>
<div class="input-group input-group-sm mb-1">
<span class="input-group-text" style="width: 180px"
>Serial handshake</span
>
<span class="input-group-text" style="width: 180px">Serial handshake</span>
<select
class="form-select form-select-sm"
@ -489,7 +482,6 @@ function saveSettings(){
aria-describedby="basic-addon1"
disabled
placeholder="auto populated from above settings"
/>
<button
class="btn btn-outline-secondary"

View file

@ -1,27 +1,21 @@
<script setup lang="ts">
import { saveSettingsToFile } from "../js/settingsHandler";
import {saveSettingsToFile} from '../js/settingsHandler'
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
function saveSettings(){
saveSettingsToFile()
function saveSettings() {
saveSettingsToFile();
}
</script>
<template>
<div class="input-group input-group-sm mb-1">
<span class="input-group-text" style="width: 180px"
>TNC port</span
>
<div class="input-group input-group-sm mb-1">
<span class="input-group-text" style="width: 180px">TNC port</span>
<input
type="text"
class="form-control"
@ -35,10 +29,8 @@ function saveSettings(){
/>
</div>
<div class="input-group input-group-sm mb-1">
<span class="input-group-text" style="width: 180px"
>TNC host</span
>
<div class="input-group input-group-sm mb-1">
<span class="input-group-text" style="width: 180px">TNC host</span>
<input
type="text"
class="form-control"
@ -49,11 +41,14 @@ function saveSettings(){
/>
</div>
<div class="input-group input-group-sm mb-1">
<label class="input-group-text w-50">TX delay in ms</label>
<select class="form-select form-select-sm" id="tx_delay" @change="saveSettings"
v-model="settings.tx_delay">
<select
class="form-select form-select-sm"
id="tx_delay"
@change="saveSettings"
v-model="settings.tx_delay"
>
<option value="0">0</option>
<option value="50">50</option>
<option value="100">100</option>
@ -81,8 +76,12 @@ function saveSettings(){
<div class="input-group input-group-sm mb-1">
<label class="input-group-text w-25">Tuning range</label>
<label class="input-group-text">fmin</label>
<select class="form-select form-select-sm" id="tuning_range_fmin" @change="saveSettings"
v-model="settings.tuning_range_fmin">
<select
class="form-select form-select-sm"
id="tuning_range_fmin"
@change="saveSettings"
v-model="settings.tuning_range_fmin"
>
<option value="-50.0">-50.0</option>
<option value="-100.0">-100.0</option>
<option value="-150.0">-150.0</option>
@ -90,8 +89,12 @@ function saveSettings(){
<option value="-250.0">-250.0</option>
</select>
<label class="input-group-text">fmax</label>
<select class="form-select form-select-sm" id="tuning_range_fmax" @change="saveSettings"
v-model="settings.tuning_range_fmax">
<select
class="form-select form-select-sm"
id="tuning_range_fmax"
@change="saveSettings"
v-model="settings.tuning_range_fmax"
>
<option value="50.0">50.0</option>
<option value="100.0">100.0</option>
<option value="150.0">150.0</option>
@ -123,7 +126,15 @@ function saveSettings(){
<label class="input-group-text w-50">Enable waterfall data</label>
<label class="input-group-text w-50">
<div class="form-check form-switch form-check-inline">
<input class="form-check-input" type="checkbox" id="fftSwitch" @change="saveSettings" v-model="settings.enable_fft" true-value="True" false-value="False"/>
<input
class="form-check-input"
type="checkbox"
id="fftSwitch"
@change="saveSettings"
v-model="settings.enable_fft"
true-value="True"
false-value="False"
/>
<label class="form-check-label" for="fftSwitch">Waterfall</label>
</div>
</label>
@ -132,7 +143,15 @@ function saveSettings(){
<label class="input-group-text w-50">Enable scatter diagram data</label>
<label class="input-group-text w-50">
<div class="form-check form-switch form-check-inline">
<input class="form-check-input" type="checkbox" id="scatterSwitch" @change="saveSettings" v-model="settings.enable_scatter" true-value="True" false-value="False"/>
<input
class="form-check-input"
type="checkbox"
id="scatterSwitch"
@change="saveSettings"
v-model="settings.enable_scatter"
true-value="True"
false-value="False"
/>
<label class="form-check-label" for="scatterSwitch">Scatter</label>
</div>
</label>
@ -145,7 +164,10 @@ function saveSettings(){
class="form-check-input"
type="checkbox"
id="250HzModeSwitch"
v-model="settings.low_bandwidth_mode" true-value="True" false-value="False" @change="saveSettings"
v-model="settings.low_bandwidth_mode"
true-value="True"
false-value="False"
@change="saveSettings"
/>
<label class="form-check-label" for="250HzModeSwitch">250Hz</label>
</div>
@ -159,7 +181,10 @@ function saveSettings(){
class="form-check-input"
type="checkbox"
id="respondCQSwitch"
v-model="settings.respond_to_cq" true-value="True" false-value="False" @change="saveSettings"
v-model="settings.respond_to_cq"
true-value="True"
false-value="False"
@change="saveSettings"
/>
<label class="form-check-label" for="respondCQSwitch">QRV</label>
</div>
@ -168,8 +193,12 @@ function saveSettings(){
<div class="input-group input-group-sm mb-1">
<label class="input-group-text w-50">RX buffer size</label>
<label class="input-group-text w-50">
<select class="form-select form-select-sm" id="rx_buffer_size" @change="saveSettings"
v-model="settings.rx_buffer_size">
<select
class="form-select form-select-sm"
id="rx_buffer_size"
@change="saveSettings"
v-model="settings.rx_buffer_size"
>
<option value="1">1</option>
<option value="2">2</option>
<option value="4">4</option>

View file

@ -1,26 +1,30 @@
<script setup lang="ts">
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
function saveSettings(){
saveSettingsToFile()
function saveSettings() {
saveSettingsToFile();
}
</script>
<template>
<div class="input-group input-group-sm mb-1">
<label class="input-group-text w-50">Explorer publishing</label>
<label class="input-group-text w-50">
<div class="form-check form-switch form-check-inline">
<input class="form-check-input" type="checkbox" id="ExplorerSwitch" @change="saveSettings" v-model="settings.enable_explorer" true-value="True" false-value="False"/>
<input
class="form-check-input"
type="checkbox"
id="ExplorerSwitch"
@change="saveSettings"
v-model="settings.enable_explorer"
true-value="True"
false-value="False"
/>
<label class="form-check-label" for="ExplorerSwitch">Publish</label>
</div>
</label>
@ -33,7 +37,10 @@ function saveSettings(){
class="form-check-input"
type="checkbox"
id="ExplorerStatsSwitch"
@change="saveSettings" v-model="settings.enable_stats" true-value="True" false-value="False"
@change="saveSettings"
v-model="settings.enable_stats"
true-value="True"
false-value="False"
/>
<label class="form-check-label" for="ExplorerStatsSwitch"
>Publish stats</label

View file

@ -3,24 +3,21 @@ const fs = require("fs");
const { v4: uuidv4 } = require("uuid");
// pinia store setup
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useChatStore } from '../store/chatStore.js';
import { useChatStore } from "../store/chatStore.js";
const chat = useChatStore(pinia);
import { sendMessage } from './sock.js';
import { sendMessage } from "./sock.js";
const FD = require("./src/js/freedata.js");
// split character
const split_char = "0;1;";
// ---- MessageDB
try {
var PouchDB = require("pouchdb");
@ -35,13 +32,10 @@ try {
var PouchDB = require("pouchdb-browser");
}
PouchDB.plugin(require("pouchdb-find"));
//PouchDB.plugin(require('pouchdb-replication'));
PouchDB.plugin(require("pouchdb-upsert"));
// https://stackoverflow.com/a/26227660
var appDataFolder =
process.env.APPDATA ||
@ -50,9 +44,6 @@ var appDataFolder =
: process.env.HOME + "/.config");
var configFolder = path.join(appDataFolder, "FreeDATA");
var chatDB = path.join(configFolder, "chatDB");
var db = new PouchDB(chatDB);
@ -60,29 +51,28 @@ var db = new PouchDB(chatDB);
createChatIndex();
// create callsign set for storing unique callsigns
chat.callsign_list = new Set()
chat.callsign_list = new Set();
// function for creating a new broadcast
export function newBroadcast(broadcastChannel, chatmessage){
var mode = ''
var frames = ''
var data = ''
if (typeof chatFile !== "undefined"){
export function newBroadcast(broadcastChannel, chatmessage) {
var mode = "";
var frames = "";
var data = "";
if (typeof chatFile !== "undefined") {
var file = chatFile;
var filetype = chatFileType
var filename = chatFileName
var filetype = chatFileType;
var filename = chatFileName;
} else {
var file = '';
var filetype = 'text'
var filename = ''
var file = "";
var filetype = "text";
var filename = "";
}
var file_checksum = ''//crc32(file).toString(16).toUpperCase();
var checksum = ''
var message_type = 'broadcast_transmit'
var command = ''
var file_checksum = ""; //crc32(file).toString(16).toUpperCase();
var checksum = "";
var message_type = "broadcast_transmit";
var command = "";
var timestamp = Math.floor(Date.now() / 1000)
var timestamp = Math.floor(Date.now() / 1000);
var uuid = uuidv4();
// TODO: Not sure what this uuid part is needed for ...
let uuidlast = uuid.lastIndexOf("-");
@ -106,62 +96,62 @@ export function newBroadcast(broadcastChannel, chatmessage){
var tnc_command = "broadcast";
sendMessage(
dxcallsign,
data_with_attachment,
checksum,
uuid,
tnc_command
)
sendMessage(dxcallsign, data_with_attachment, checksum, uuid, tnc_command);
let newChatObj = new Object();
newChatObj.command = "msg"
newChatObj.hmac_signed = false
newChatObj.percent = 0
newChatObj.bytesperminute
newChatObj.is_new = false
newChatObj._id = uuid
newChatObj.timestamp = timestamp
newChatObj.dxcallsign = dxcallsign
newChatObj.dxgrid = "null"
newChatObj.msg = chatmessage
newChatObj.checksum = file_checksum
newChatObj.type = message_type
newChatObj.status = "transmitting"
newChatObj.attempt = 1
newChatObj.uuid = uuid
newChatObj.command = "msg";
newChatObj.hmac_signed = false;
newChatObj.percent = 0;
newChatObj.bytesperminute;
newChatObj.is_new = false;
newChatObj._id = uuid;
newChatObj.timestamp = timestamp;
newChatObj.dxcallsign = dxcallsign;
newChatObj.dxgrid = "null";
newChatObj.msg = chatmessage;
newChatObj.checksum = file_checksum;
newChatObj.type = message_type;
newChatObj.status = "transmitting";
newChatObj.attempt = 1;
newChatObj.uuid = uuid;
newChatObj._attachments = {
[filename]: {
content_type: filetype,
data: FD.btoa_FD(file),
},
}
addObjToDatabase(newChatObj)
};
addObjToDatabase(newChatObj);
}
// function for creating a new message
export function newMessage(dxcallsign, chatmessage, chatFile, chatFileName, chatFileSize, chatFileType){
var mode = ''
var frames = ''
var data = ''
if (typeof chatFile !== "undefined"){
export function newMessage(
dxcallsign,
chatmessage,
chatFile,
chatFileName,
chatFileSize,
chatFileType,
) {
var mode = "";
var frames = "";
var data = "";
if (typeof chatFile !== "undefined") {
var file = chatFile;
var filetype = chatFileType
var filename = chatFileName
var filetype = chatFileType;
var filename = chatFileName;
} else {
var file = '';
var filetype = 'text'
var filename = ''
var file = "";
var filetype = "text";
var filename = "";
}
var file_checksum = ''//crc32(file).toString(16).toUpperCase();
var checksum = ''
var message_type = 'transmit'
var command = ''
var file_checksum = ""; //crc32(file).toString(16).toUpperCase();
var checksum = "";
var message_type = "transmit";
var command = "";
var timestamp = Math.floor(Date.now() / 1000)
var timestamp = Math.floor(Date.now() / 1000);
var uuid = uuidv4();
// TODO: Not sure what this uuid part is needed for ...
let uuidlast = uuid.lastIndexOf("-");
@ -172,9 +162,6 @@ export function newMessage(dxcallsign, chatmessage, chatFile, chatFileName, chat
// slice uuid for reducing overhead
uuid = uuid.slice(-8);
var data_with_attachment =
timestamp +
split_char +
@ -188,52 +175,42 @@ export function newMessage(dxcallsign, chatmessage, chatFile, chatFileName, chat
var tnc_command = "msg";
sendMessage(
dxcallsign,
data_with_attachment,
checksum,
uuid,
tnc_command
)
sendMessage(dxcallsign, data_with_attachment, checksum, uuid, tnc_command);
let newChatObj = new Object();
newChatObj.command = "msg"
newChatObj.hmac_signed = false
newChatObj.percent = 0
newChatObj.bytesperminute
newChatObj.is_new = false
newChatObj._id = uuid
newChatObj.timestamp = timestamp
newChatObj.dxcallsign = dxcallsign
newChatObj.dxgrid = "null"
newChatObj.msg = chatmessage
newChatObj.checksum = file_checksum
newChatObj.type = message_type
newChatObj.status = "transmitting"
newChatObj.attempt = 1
newChatObj.uuid = uuid
newChatObj.command = "msg";
newChatObj.hmac_signed = false;
newChatObj.percent = 0;
newChatObj.bytesperminute;
newChatObj.is_new = false;
newChatObj._id = uuid;
newChatObj.timestamp = timestamp;
newChatObj.dxcallsign = dxcallsign;
newChatObj.dxgrid = "null";
newChatObj.msg = chatmessage;
newChatObj.checksum = file_checksum;
newChatObj.type = message_type;
newChatObj.status = "transmitting";
newChatObj.attempt = 1;
newChatObj.uuid = uuid;
newChatObj._attachments = {
[filename]: {
content_type: filetype,
data: FD.btoa_FD(file),
},
}
addObjToDatabase(newChatObj)
};
addObjToDatabase(newChatObj);
}
// function for creating a list, accessible by callsign
function sortChatList(){
function sortChatList() {
// Create an empty object to store the reordered data dynamically
var reorderedData = {};
var jsonObjects = chat.unsorted_chat_list
var jsonObjects = chat.unsorted_chat_list;
// Iterate through the list of JSON objects and reorder them dynamically
jsonObjects.forEach(obj => {
jsonObjects.forEach((obj) => {
var dxcallsign = obj.dxcallsign;
if (dxcallsign) {
if (!reorderedData[dxcallsign]) {
@ -243,87 +220,78 @@ function sortChatList(){
}
});
//console.log(reorderedData["DJ2LS-0"])
return reorderedData
return reorderedData;
}
//repeat a message
export function repeatMessageTransmission(id){
console.log(id)
export function repeatMessageTransmission(id) {
console.log(id);
}
// delete a message from databse and gui
export function deleteMessageFromDB(id){
console.log("deleting: " + id)
export function deleteMessageFromDB(id) {
console.log("deleting: " + id);
db.get(id).then(function (doc) {
db.remove(doc)
})
db.remove(doc);
});
// overwrote unsorted chat list by filtering if not ID
chat.unsorted_chat_list = chat.unsorted_chat_list.filter(entry => entry.uuid !== id);
chat.unsorted_chat_list = chat.unsorted_chat_list.filter(
(entry) => entry.uuid !== id,
);
// and finally generate our sorted chat list, which is the key store for chat gui rendering
// the removed entry should be removed now from gui
chat.sorted_chat_list = sortChatList()
chat.sorted_chat_list = sortChatList();
}
// function to update transmission status
export function updateTransmissionStatus(obj){
export function updateTransmissionStatus(obj) {
// update database entries
databaseUpsert(obj.uuid, "percent", obj.percent)
databaseUpsert(obj.uuid, "bytesperminute", obj.bytesperminute)
databaseUpsert(obj.uuid, "status", obj.status)
databaseUpsert(obj.uuid, "percent", obj.percent);
databaseUpsert(obj.uuid, "bytesperminute", obj.bytesperminute);
databaseUpsert(obj.uuid, "status", obj.status);
// update screen rendering / messages
updateUnsortedChatListEntry(obj.uuid, "percent", obj.percent)
updateUnsortedChatListEntry(obj.uuid, "bytesperminute", obj.bytesperminute)
updateUnsortedChatListEntry(obj.uuid, "status", obj.status)
updateUnsortedChatListEntry(obj.uuid, "percent", obj.percent);
updateUnsortedChatListEntry(obj.uuid, "bytesperminute", obj.bytesperminute);
updateUnsortedChatListEntry(obj.uuid, "status", obj.status);
}
export function updateUnsortedChatListEntry(uuid, object, value){
export function updateUnsortedChatListEntry(uuid, object, value) {
for (const entry of chat.unsorted_chat_list) {
if (entry.uuid === uuid) {
entry[object] = value
console.log("Entry updated:", entry[object])
chat.sorted_chat_list = sortChatList()
return entry
entry[object] = value;
console.log("Entry updated:", entry[object]);
chat.sorted_chat_list = sortChatList();
return entry;
}
}
console.log("Entry not updated:", object)
console.log("Entry not updated:", object);
return null; // Return null if not found
}
export function databaseUpsert(id, object, value){
export function databaseUpsert(id, object, value) {
db.upsert(id, function (doc) {
if (!doc[object]) {
doc[object] = value;
}
doc[object] = value;
return doc;
}).then(function (res) {
})
.then(function (res) {
// success, res is {rev: '1-xxx', updated: true, id: 'myDocId'}
console.log(res)
}).catch(function (err) {
console.log(res);
})
.catch(function (err) {
// error
console.log(err)
console.log(err);
});
}
// function for fetching all messages from chat / updating chat
export async function updateAllChat() {
//Ensure we create an index before running db.find
//We can't rely on the default index existing before we get here...... :'(
await db
@ -348,15 +316,14 @@ export async function updateAllChat() {
})
.then(async function (result) {
for (var item of result.docs) {
if(item.type === 'beacon'){
console.log(item)
if (item.type === "beacon") {
console.log(item);
// TODO: sort beacon list .... maybe a part for a separate function
const jsonData = [item]
const dxcallsign = obj.dxcallsign
const jsonData = [item];
const dxcallsign = obj.dxcallsign;
// Process each JSON item step by step
jsonData.forEach(jsonitem => {
jsonData.forEach((jsonitem) => {
const { snr, timestamp } = item;
// Check if dxcallsign already exists as a property in the result object
@ -372,25 +339,14 @@ export async function updateAllChat() {
// Push the snr value to the corresponding dxcallsign's snr array
chat.sorted_beacon_list[dxcallsign].snr.push(snr);
chat.sorted_beacon_list[dxcallsign].timestamp.push(timestamp);
});
} else {
chat.callsign_list.add(item.dxcallsign)
chat.unsorted_chat_list.push(item)
chat.callsign_list.add(item.dxcallsign);
chat.unsorted_chat_list.push(item);
}
}
chat.sorted_chat_list = sortChatList()
chat.sorted_chat_list = sortChatList();
/*
if (typeof result !== "undefined") {
@ -406,8 +362,6 @@ export async function updateAllChat() {
}
}
*/
})
.catch(function (err) {
console.log(err);
@ -416,11 +370,10 @@ export async function updateAllChat() {
.catch(function (err) {
console.log(err);
});
}
function addObjToDatabase(newobj){
console.log(newobj)
function addObjToDatabase(newobj) {
console.log(newobj);
/*
db.upsert(newobj._id, function (doc) {
if (!doc._id) {
@ -440,14 +393,13 @@ function addObjToDatabase(newobj){
console.log(err);
});
console.log(newobj)
if(newobj.command === 'msg'){
chat.unsorted_chat_list.push(newobj)
chat.sorted_chat_list = sortChatList()
console.log(newobj);
if (newobj.command === "msg") {
chat.unsorted_chat_list.push(newobj);
chat.sorted_chat_list = sortChatList();
}
/*
/*
// upsert footer ...
}
@ -456,8 +408,6 @@ function addObjToDatabase(newobj){
*/
}
function createChatIndex() {
db.createIndex({
index: {
@ -489,19 +439,16 @@ function createChatIndex() {
});
}
export function deleteChatByCallsign(callsign) {
chat.callsign_list.delete(callsign);
delete chat.unsorted_chat_list.callsign;
delete chat.sorted_chat_list.callsign;
export function deleteChatByCallsign(callsign){
chat.callsign_list.delete(callsign)
delete chat.unsorted_chat_list.callsign
delete chat.sorted_chat_list.callsign
deleteFromDatabaseByCallsign(callsign)
deleteFromDatabaseByCallsign(callsign);
}
function deleteFromDatabaseByCallsign(callsign){
db.find({
function deleteFromDatabaseByCallsign(callsign) {
db.find({
selector: {
dxcallsign: callsign,
},
@ -533,10 +480,9 @@ db.find({
});
}
// function for handling a received beacon
export function newBeaconReceived(obj){
/*
export function newBeaconReceived(obj) {
/*
{
"freedata": "tnc-message",
"beacon": "received",
@ -550,25 +496,24 @@ export function newBeaconReceived(obj){
*/
let newChatObj = new Object();
newChatObj.command = "beacon"
newChatObj._id = obj['uuid']
newChatObj.uuid = obj['uuid']
newChatObj.timestamp = obj['timestamp']
newChatObj.dxcallsign = obj["dxcallsign"]
newChatObj.dxgrid = obj["dxgrid"]
newChatObj.type = 'beacon'
newChatObj.status = obj["beacon"]
newChatObj.snr = obj["snr"]
newChatObj.command = "beacon";
newChatObj._id = obj["uuid"];
newChatObj.uuid = obj["uuid"];
newChatObj.timestamp = obj["timestamp"];
newChatObj.dxcallsign = obj["dxcallsign"];
newChatObj.dxgrid = obj["dxgrid"];
newChatObj.type = "beacon";
newChatObj.status = obj["beacon"];
newChatObj.snr = obj["snr"];
addObjToDatabase(newChatObj);
addObjToDatabase(newChatObj)
console.log(obj);
console.log(obj)
const jsonData = [obj]
const dxcallsign = obj.dxcallsign
// Process each JSON item step by step
jsonData.forEach(item => {
const jsonData = [obj];
const dxcallsign = obj.dxcallsign;
// Process each JSON item step by step
jsonData.forEach((item) => {
const { snr, timestamp } = obj;
// Check if dxcallsign already exists as a property in the result object
@ -584,15 +529,11 @@ jsonData.forEach(item => {
// Push the snr value to the corresponding dxcallsign's snr array
chat.sorted_beacon_list[dxcallsign].snr.push(snr);
chat.sorted_beacon_list[dxcallsign].timestamp.push(timestamp);
});
});
}
// function for handling a received message
export function newMessageReceived(message, protocol){
export function newMessageReceived(message, protocol) {
/*
PROTOCOL
@ -629,56 +570,53 @@ export function newMessageReceived(message, protocol){
*/
console.log(protocol)
console.log(protocol);
let newChatObj = new Object();
newChatObj.command = "msg"
newChatObj.hmac_signed = protocol["hmac_signed"]
newChatObj.percent = 100
newChatObj.bytesperminute = protocol["bytesperminute"]
newChatObj.is_new = true
newChatObj._id = message[3]
newChatObj.timestamp = message[4]
newChatObj.dxcallsign = protocol["dxcallsign"]
newChatObj.dxgrid = protocol["dxgrid"]
newChatObj.msg = message[5]
newChatObj.checksum = message[2]
newChatObj.type = message[1]
newChatObj.status = protocol["status"]
newChatObj.attempt = 1
newChatObj.uuid = message[3]
newChatObj.command = "msg";
newChatObj.hmac_signed = protocol["hmac_signed"];
newChatObj.percent = 100;
newChatObj.bytesperminute = protocol["bytesperminute"];
newChatObj.is_new = true;
newChatObj._id = message[3];
newChatObj.timestamp = message[4];
newChatObj.dxcallsign = protocol["dxcallsign"];
newChatObj.dxgrid = protocol["dxgrid"];
newChatObj.msg = message[5];
newChatObj.checksum = message[2];
newChatObj.type = message[1];
newChatObj.status = protocol["status"];
newChatObj.attempt = 1;
newChatObj.uuid = message[3];
newChatObj._attachments = {
[message[6]]: {
content_type: message[7],
data: FD.btoa_FD(message[8]),
},
}
};
// some tweaks for broadcasts
if (protocol.fec == "broadcast") {
newChatObj.broadcast_sender = protocol["dxcallsign"]
newChatObj.type = 'broadcast_received'
newChatObj.broadcast_sender = protocol["dxcallsign"];
newChatObj.type = "broadcast_received";
}
addObjToDatabase(newChatObj)
addObjToDatabase(newChatObj);
}
export function setStateFailed(){
state.arq_seconds_until_finish = 0
state.arq_seconds_until_timeout = 180
state.arq_seconds_until_timeout_percent = 100
export function setStateFailed() {
state.arq_seconds_until_finish = 0;
state.arq_seconds_until_timeout = 180;
state.arq_seconds_until_timeout_percent = 100;
}
export function setStateSuccess(){
state.arq_seconds_until_finish = 0
state.arq_seconds_until_timeout = 180
state.arq_seconds_until_timeout_percent = 100
export function setStateSuccess() {
state.arq_seconds_until_finish = 0;
state.arq_seconds_until_timeout = 180;
state.arq_seconds_until_timeout_percent = 100;
}
// CRC CHECKSUMS
// https://stackoverflow.com/a/50579690
// crc32 calculation
@ -709,7 +647,3 @@ var crc32 = function (str) {
return (crc ^ -1) >>> 0;
};

View file

@ -1,19 +1,19 @@
//var net = require("net");
var net = require('node:net');
var net = require("node:net");
const path = require("path");
const { ipcRenderer } = require("electron");
// ----------------- init pinia stores -------------
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useAudioStore } from '../store/audioStore.js';
import { useAudioStore } from "../store/audioStore.js";
const audioStore = useAudioStore(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
var daemon = new net.Socket();
@ -22,7 +22,6 @@ var socketchunk = ""; // Current message, per connection.
// global to keep track of daemon connection error emissions
var daemonShowConnectStateError = 1;
setTimeout(connectDAEMON, 500);
function connectDAEMON() {
@ -33,7 +32,6 @@ function connectDAEMON() {
//clear message buffer after reconnecting or initial connection
socketchunk = "";
daemon.connect(settings.daemon_port, settings.daemon_host);
//client.setTimeout(5000);
@ -89,7 +87,6 @@ daemon.on("end", function (data) {
//exports.writeDaemonCommand = function(command){
//writeDaemonCommand = function (command) {
function writeDaemonCommand(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") {
@ -109,7 +106,7 @@ function writeDaemonCommand(command) {
daemon_connection: daemon.readyState,
};
ipcRenderer.send("request-update-daemon-connection", Data);
};
}
// "https://stackoverflow.com/questions/9070700/nodejs-net-createserver-large-amount-of-data-coming-in"
@ -168,8 +165,6 @@ daemon.on("data", function (socketdata) {
audioStore.inputDevices = data["input_devices"];
audioStore.outputDevices = data["output_devices"];
state.tnc_running_state = data["daemon_state"][0]["status"];
}
if (data["command"] == "test_hamlib") {
@ -193,11 +188,10 @@ function hexToBytes(hex) {
//exports.getDaemonState = function () {
function getDaemonState() {
//function getDaemonState(){
command = '{"type" : "get", "command" : "daemon_state"}';
writeDaemonCommand(command);
};
}
// START TNC
// ` `== multi line string
@ -244,20 +238,18 @@ export function startTNC() {
console.log(json_command);
writeDaemonCommand(json_command);
};
}
// STOP TNC
//exports.stopTNC = function () {
export function stopTNC() {
var command = '{"type" : "set", "command": "stop_tnc" , "parameter": "---" }';
writeDaemonCommand(command);
};
}
// TEST HAMLIB
function testHamlib(
//exports.testHamlib = function (
//exports.testHamlib = function (
radiocontrol,
devicename,
deviceport,
@ -291,26 +283,25 @@ function testHamlib(
});
console.log(json_command);
writeDaemonCommand(json_command);
};
}
//Save myCall
function saveMyCall(callsign){
//exports.saveMyCall = function (callsign) {
function saveMyCall(callsign) {
//exports.saveMyCall = function (callsign) {
command =
'{"type" : "set", "command": "mycallsign" , "parameter": "' +
callsign +
'"}';
writeDaemonCommand(command);
};
}
// Save myGrid
//exports.saveMyGrid = function (grid) {
function saveMyGrid(grid){
function saveMyGrid(grid) {
command =
'{"type" : "set", "command": "mygrid" , "parameter": "' + grid + '"}';
writeDaemonCommand(command);
};
}
ipcRenderer.on("action-update-daemon-ip", (event, arg) => {
daemon.destroy();

View file

@ -1,6 +1,5 @@
const fs = require("fs");
/**
* Binary to ASCII replacement
* @param {string} data in normal/usual utf-8 format
@ -25,5 +24,3 @@ exports.atob_FD = function (data) {
exports.atob = function (data) {
return window.btoa(Buffer.from(data, "base64").toString("utf8"));
};

View file

@ -1,14 +1,7 @@
const { v4: uuidv4 } = require("uuid");
import * as bootstrap from 'bootstrap'
import * as bootstrap from "bootstrap";
export function displayToast(
type,
icon,
content,
duration,
) {
export function displayToast(type, icon, content, duration) {
let mainToastContainer = document.getElementById("mainToastContainer");
let randomID = uuidv4();

View file

@ -2,17 +2,16 @@
//const fs = require("fs");
//const os = require("os");
import path from 'node:path'
import fs from 'fs'
import os from 'os'
import path from "node:path";
import fs from "fs";
import os from "os";
// pinia store setup
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
// ---------------------------------
@ -94,18 +93,17 @@ if (!fs.existsSync(configPath)) {
fs.writeFileSync(configPath, configDefaultSettings);
}
export function loadSettings() {
// load settings
var config = require(configPath);
export function loadSettings(){
// load settings
var config = require(configPath);
//config validation
// check running config against default config.
// if parameter not exists, add it to running config to prevent errors
console.log("CONFIG VALIDATION ----------------------------- ");
//config validation
// check running config against default config.
// if parameter not exists, add it to running config to prevent errors
console.log("CONFIG VALIDATION ----------------------------- ");
var parsedConfig = JSON.parse(configDefaultSettings);
for (var key in parsedConfig) {
var parsedConfig = JSON.parse(configDefaultSettings);
for (var key in parsedConfig) {
if (config.hasOwnProperty(key)) {
console.log("FOUND SETTTING [" + key + "]: " + config[key]);
} else {
@ -113,29 +111,22 @@ for (var key in parsedConfig) {
config[key] = parsedConfig[key];
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
}
try{
if (key == "mycall"){
settings.mycall = config[key].split("-")[0]
settings.myssid = config[key].split("-")[1]
try {
if (key == "mycall") {
settings.mycall = config[key].split("-")[0];
settings.myssid = config[key].split("-")[1];
} else {
settings[key] = config[key];
}
} catch(e){
console.log(e)
} catch (e) {
console.log(e);
}
}
}
}
export function saveSettingsToFile(){
console.log("save settings to file...")
let config = settings.getJSON()
console.log(config)
export function saveSettingsToFile() {
console.log("save settings to file...");
let config = settings.getJSON();
console.log(config);
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
}

View file

@ -2,32 +2,32 @@ var net = require("net");
const path = require("path");
const FD = require("./src/js/freedata.js");
//import FD from './freedata.js';
import { newMessageReceived, newBeaconReceived, updateTransmissionStatus, setStateSuccess, setStateFailed } from './chatHandler.js';
import {displayToast} from './popupHandler.js'
import {
newMessageReceived,
newBeaconReceived,
updateTransmissionStatus,
setStateSuccess,
setStateFailed,
} from "./chatHandler.js";
import { displayToast } from "./popupHandler.js";
// ----------------- init pinia stores -------------
import { setActivePinia } from 'pinia';
import pinia from '../store/index';
import { setActivePinia } from "pinia";
import pinia from "../store/index";
setActivePinia(pinia);
import { useStateStore } from '../store/stateStore.js';
import { useStateStore } from "../store/stateStore.js";
const stateStore = useStateStore(pinia);
import { useSettingsStore } from '../store/settingsStore.js';
import { useSettingsStore } from "../store/settingsStore.js";
const settings = useSettingsStore(pinia);
var client = new net.Socket();
var socketchunk = ""; // Current message, per connection.
// split character
//const split_char = "\0;\1;";
const split_char = "0;1;";
// globals for getting new data only if available so we are saving bandwidth
var rxBufferLengthTnc = 0;
var rxBufferLengthGui = 0;
@ -37,7 +37,6 @@ var rxBufferLengthGui = 0;
// global to keep track of TNC connection error emissions
var tncShowConnectStateError = 1;
// network connection Timeout
setTimeout(connectTNC, 2000);
@ -48,9 +47,7 @@ function connectTNC() {
//clear message buffer after reconnecting or initial connection
socketchunk = "";
client.connect(settings.tnc_port, settings.tnc_host);
}
client.on("connect", function (data) {
@ -62,7 +59,7 @@ client.on("connect", function (data) {
stateStore.mode = "-";
stateStore.bandwidth = "-";
stateStore.dbfs_level = 0;
stateStore.updateTncState(client.readyState)
stateStore.updateTncState(client.readyState);
tncShowConnectStateError = 1;
});
@ -80,8 +77,7 @@ client.on("error", function (data) {
stateStore.mode = "-";
stateStore.bandwidth = "-";
stateStore.dbfs_level = 0;
stateStore.updateTncState(client.readyState)
stateStore.updateTncState(client.readyState);
});
/*
@ -99,14 +95,14 @@ client.on("end", function (data) {
stateStore.mode = "-";
stateStore.bandwidth = "-";
stateStore.dbfs_level = 0;
stateStore.updateTncState(client.readyState)
stateStore.updateTncState(client.readyState);
client.destroy();
setTimeout(connectTNC, 500);
});
function writeTncCommand(command) {
console.log(command)
console.log(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
@ -121,11 +117,10 @@ function writeTncCommand(command) {
if (client.readyState == "opening") {
console.log("connecting to TNC...");
}
};
}
client.on("data", function (socketdata) {
stateStore.updateTncState(client.readyState)
stateStore.updateTncState(client.readyState);
/*
inspired by:
@ -174,60 +169,64 @@ client.on("data", function (socketdata) {
rxBufferLengthTnc = data["rx_buffer_length"];
//rxMsgBufferLengthTnc = data["rx_msg_buffer_length"];
stateStore.frequency = data["frequency"]
stateStore.busy_state = data["tnc_state"]
stateStore.arq_state = data["arq_state"]
stateStore.mode = data["mode"]
stateStore.bandwidth = data["bandwidth"]
stateStore.dbfs_level = data["audio_dbfs"]
stateStore.ptt_state = data["ptt_state"]
stateStore.speed_level = data["speed_level"]
stateStore.fft = data["fft"]
stateStore.channel_busy = data["channel_busy"]
stateStore.channel_busy_slot = data["channel_busy_slot"]
stateStore.frequency = data["frequency"];
stateStore.busy_state = data["tnc_state"];
stateStore.arq_state = data["arq_state"];
stateStore.mode = data["mode"];
stateStore.bandwidth = data["bandwidth"];
stateStore.dbfs_level = data["audio_dbfs"];
stateStore.ptt_state = data["ptt_state"];
stateStore.speed_level = data["speed_level"];
stateStore.fft = data["fft"];
stateStore.channel_busy = data["channel_busy"];
stateStore.channel_busy_slot = data["channel_busy_slot"];
if(data["scatter"].length > 0){
stateStore.scatter = data["scatter"]
if (data["scatter"].length > 0) {
stateStore.scatter = data["scatter"];
}
// s meter strength
stateStore.s_meter_strength_raw = data["strength"]
stateStore.s_meter_strength_raw = data["strength"];
if (stateStore.s_meter_strength_raw == "") {
stateStore.s_meter_strength_raw = "Unsupported"
stateStore.s_meter_strength_percent = 0
stateStore.s_meter_strength_raw = "Unsupported";
stateStore.s_meter_strength_percent = 0;
} else {
// https://www.moellerstudios.org/converting-amplitude-representations/
stateStore.s_meter_strength_percent = Math.round(Math.pow(10, stateStore.s_meter_strength_raw / 20) * 100);
stateStore.s_meter_strength_percent = Math.round(
Math.pow(10, stateStore.s_meter_strength_raw / 20) * 100,
);
}
stateStore.dbfs_level_percent = Math.round(Math.pow(10, stateStore.dbfs_level / 20) * 100);
stateStore.dbfs_level = Math.round(stateStore.dbfs_level)
stateStore.dbfs_level_percent = Math.round(
Math.pow(10, stateStore.dbfs_level / 20) * 100,
);
stateStore.dbfs_level = Math.round(stateStore.dbfs_level);
stateStore.arq_total_bytes = data["total_bytes"];
stateStore.heard_stations = data["stations"];
stateStore.dxcallsign = data["dxcallsign"];
stateStore.arq_total_bytes = data["total_bytes"]
stateStore.heard_stations = data["stations"]
stateStore.dxcallsign = data["dxcallsign"]
stateStore.beacon_state = data["beacon_state"];
stateStore.audio_recording = data["audio_recording"];
stateStore.beacon_state = data["beacon_state"]
stateStore.audio_recording = data["audio_recording"]
stateStore.hamlib_status = data["hamlib_status"];
stateStore.alc = data["alc"];
stateStore.rf_level = data["rf_level"];
stateStore.hamlib_status = data["hamlib_status"]
stateStore.alc = data["alc"]
stateStore.rf_level = data["rf_level"]
stateStore.is_codec2_traffic = data["is_codec2_traffic"];
stateStore.is_codec2_traffic = data["is_codec2_traffic"]
stateStore.arq_session_state = data["arq_session"];
stateStore.arq_state = data["arq_state"];
stateStore.arq_transmission_percent = data["arq_transmission_percent"];
stateStore.arq_seconds_until_finish = data["arq_seconds_until_finish"];
stateStore.arq_seconds_until_timeout =
data["arq_seconds_until_timeout"];
stateStore.arq_seconds_until_timeout_percent =
(stateStore.arq_seconds_until_timeout / 180) * 100;
stateStore.arq_session_state = data["arq_session"]
stateStore.arq_state = data["arq_state"]
stateStore.arq_transmission_percent = data["arq_transmission_percent"]
stateStore.arq_seconds_until_finish = data["arq_seconds_until_finish"]
stateStore.arq_seconds_until_timeout = data["arq_seconds_until_timeout"]
stateStore.arq_seconds_until_timeout_percent = (stateStore.arq_seconds_until_timeout / 180) * 100
if(data["speed_list"].length > 0){
prepareStatsDataForStore(data["speed_list"])
if (data["speed_list"].length > 0) {
prepareStatsDataForStore(data["speed_list"]);
}
// TODO: Remove ported objects
let Data = {
mycallsign: data["mycallsign"],
@ -260,19 +259,16 @@ client.on("data", function (socketdata) {
// ----------- catch tnc messages START -----------
//init message variable
var message = ''
var message = "";
if (data["freedata"] == "tnc-message") {
// break early if we received a dummy callsign
// thats a kind of hotfix, as long as the tnc isnt handling this better
if (data["dxcallsign"] == "AA0AA-0"){
break
if (data["dxcallsign"] == "AA0AA-0") {
break;
}
console.log(data);
switch (data["fec"]) {
case "is_writing":
// RX'd FECiswriting
@ -293,12 +289,17 @@ client.on("data", function (socketdata) {
switch (data["cq"]) {
case "transmitting":
// CQ TRANSMITTING
displayToast("success", "bi-arrow-left-right", "transmitting CQ", 5000);
displayToast(
"success",
"bi-arrow-left-right",
"transmitting CQ",
5000,
);
break;
case "received":
// CQ RECEIVED
message = "CQ from " + data['dxcallsign']
message = "CQ from " + data["dxcallsign"];
displayToast("success", "bi-arrow-left-right", message, 5000);
break;
}
@ -306,12 +307,17 @@ client.on("data", function (socketdata) {
switch (data["qrv"]) {
case "transmitting":
// QRV TRANSMITTING
displayToast("success", "bi-arrow-left-right", "transmitting QRV ", 5000);
displayToast(
"success",
"bi-arrow-left-right",
"transmitting QRV ",
5000,
);
break;
case "received":
// QRV RECEIVED
message = "QRV from " + data['dxcallsign'] + " | " + data['dxgrid']
message = "QRV from " + data["dxcallsign"] + " | " + data["dxgrid"];
displayToast("success", "bi-arrow-left-right", message, 5000);
break;
}
@ -324,9 +330,10 @@ client.on("data", function (socketdata) {
case "received":
// BEACON RECEIVED
newBeaconReceived(data)
newBeaconReceived(data);
message = "BEACON from " + data['dxcallsign'] + " | " + data['dxgrid']
message =
"BEACON from " + data["dxcallsign"] + " | " + data["dxgrid"];
displayToast("success", "bi-arrow-left-right", message, 5000);
break;
}
@ -334,19 +341,21 @@ client.on("data", function (socketdata) {
switch (data["ping"]) {
case "transmitting":
// PING TRANSMITTING
message = "PING to " + data['dxcallsign']
message = "PING to " + data["dxcallsign"];
displayToast("success", "bi-arrow-left-right", message, 5000);
break;
case "received":
// PING RECEIVED
message = "PING from " + data['dxcallsign'] + " | " + data['dxgrid']
message =
"PING from " + data["dxcallsign"] + " | " + data["dxgrid"];
displayToast("success", "bi-arrow-left-right", message, 5000);
break;
case "acknowledge":
// PING ACKNOWLEDGE
message = "PING ACK from " + data['dxcallsign'] + " | " + data['dxgrid']
message =
"PING ACK from " + data["dxcallsign"] + " | " + data["dxgrid"];
displayToast("success", "bi-arrow-left-right", message, 5000);
break;
}
@ -380,29 +389,27 @@ client.on("data", function (socketdata) {
switch (data["status"]) {
case "opened":
// ARQ Open
message = "ARQ session opened:" + data['dxcallsign']
message = "ARQ session opened:" + data["dxcallsign"];
displayToast("success", "bi-arrow-left-right", message, 5000);
break;
case "opening":
// ARQ Opening IRS/ISS
if (data["irs"] == "False") {
message = "ARQ session opening:" + data['dxcallsign']
message = "ARQ session opening:" + data["dxcallsign"];
displayToast("success", "bi-arrow-left-right", message, 5000);
break;
} else {
message = data['dxcallsign'] + "is requesting an ARQ session"
message = data["dxcallsign"] + "is requesting an ARQ session";
displayToast("success", "bi-arrow-left-right", message, 5000);
break;
}
break;
case "waiting":
// ARQ waiting
message = "busy channel | ARQ protocol is waiting"
message = "busy channel | ARQ protocol is waiting";
displayToast("success", "bi-arrow-left-right", message, 5000);
break;
@ -413,26 +420,25 @@ client.on("data", function (socketdata) {
case "failed":
// ARQ TX Failed
if (data["reason"] == "protocol version missmatch") {
message = "protocol version missmatch"
message = "protocol version missmatch";
displayToast("success", "bi-arrow-left-right", message, 5000);
setStateFailed()
setStateFailed();
break;
} else {
message = "transmission failed"
message = "transmission failed";
displayToast("success", "bi-arrow-left-right", message, 5000);
updateTransmissionStatus(data)
setStateFailed()
updateTransmissionStatus(data);
setStateFailed();
break;
}
switch (data["irs"]) {
case "True":
updateTransmissionStatus(data)
updateTransmissionStatus(data);
break;
default:
updateTransmissionStatus(data)
updateTransmissionStatus(data);
break;
}
break;
@ -448,30 +454,29 @@ client.on("data", function (socketdata) {
// new message received
if (splitted_data[0] == "m") {
console.log(splitted_data)
newMessageReceived(splitted_data, data)
console.log(splitted_data);
newMessageReceived(splitted_data, data);
}
break;
case "transmitting":
// ARQ transmitting
updateTransmissionStatus(data)
updateTransmissionStatus(data);
break;
case "transmitted":
// ARQ transmitted
message = "data transmitted"
message = "data transmitted";
displayToast("success", "bi-arrow-left-right", message, 5000);
updateTransmissionStatus(data)
setStateSuccess()
updateTransmissionStatus(data);
setStateSuccess();
break;
}
}
}
// ----------- catch tnc info messages END -----------
// if we manually checking for the rx buffer we are getting an array of multiple data
@ -488,7 +493,6 @@ client.on("data", function (socketdata) {
var encoded_data = FD.atob_FD(data["data-array"][i]["data"]);
var splitted_data = encoded_data.split(split_char);
if (splitted_data[0] == "m") {
messageArray.push(data["data-array"][i]);
}
@ -508,7 +512,6 @@ client.on("data", function (socketdata) {
//finally delete message buffer
socketchunk = "";
}
});
function hexToBytes(hex) {
@ -519,52 +522,51 @@ function hexToBytes(hex) {
//Get TNC State
//exports.getTncState = function () {
function getTncState(){
function getTncState() {
var command = '{"type" : "get", "command" : "tnc_state"}';
writeTncCommand(command);
};
}
//Get DATA State
//exports.getDataState = function () {
function getDataState(){
function getDataState() {
var command = '{"type" : "get", "command" : "data_state"}';
//writeTncCommand(command)
};
}
// Send Ping
//exports.sendPing = function (dxcallsign) {
export function sendPing(dxcallsign){
export function sendPing(dxcallsign) {
var command =
'{"type" : "ping", "command" : "ping", "dxcallsign" : "' +
dxcallsign +
'"}';
writeTncCommand(command);
};
}
// Send Mesh Ping
//exports.sendMeshPing = function (dxcallsign) {
function sendMeshPing(dxcallsign){
function sendMeshPing(dxcallsign) {
command =
'{"type" : "mesh", "command" : "ping", "dxcallsign" : "' +
dxcallsign +
'"}';
writeTncCommand(command);
};
}
// Send CQ
//exports.sendCQ = function () {
export function sendCQ(){
export function sendCQ() {
var command = '{"type" : "broadcast", "command" : "cqcqcq"}';
writeTncCommand(command);
};
}
// Set AUDIO Level
export function setTxAudioLevel(value){
export function setTxAudioLevel(value) {
var command =
'{"type" : "set", "command" : "tx_audio_level", "value" : "' + value + '"}';
writeTncCommand(command);
};
}
// Send File
//exports.sendFile = function (
@ -611,16 +613,10 @@ function sendFile(
data +
'"}]}';
writeTncCommand(command);
};
}
// Send Message
export function sendMessage(
dxcallsign,
data,
checksum,
uuid,
command,
) {
export function sendMessage(dxcallsign, data, checksum, uuid, command) {
data = FD.btoa_FD(
"m" +
split_char +
@ -634,9 +630,8 @@ export function sendMessage(
);
// TODO: REMOVE mode and frames from TNC!
var mode = 255
var frames = 5
var mode = 255;
var frames = 5;
command =
'{"type" : "arq", "command" : "send_raw", "uuid" : "' +
@ -652,7 +647,7 @@ export function sendMessage(
'", "attempts": "10"}]}';
console.log(command);
writeTncCommand(command);
};
}
// Send Request message
//It would be then „m + split + request + split + request-type“
@ -694,57 +689,52 @@ function sendResponse(dxcallsign, mode, frames, data, command) {
//Send station info request
//exports.sendRequestInfo = function (dxcallsign) {
function sendRequestInfo(dxcallsign){
function sendRequestInfo(dxcallsign) {
//Command 0 = user/station information
//Command 1 = shared folder list
//Command 2 = shared file transfer
sendRequest(dxcallsign, 255, 1, "0", "req");
};
}
//Send shared folder file list request
//exports.sendRequestSharedFolderList = function (dxcallsign) {
function sendRequestSharedFolderList(dxcallsign){
function sendRequestSharedFolderList(dxcallsign) {
//Command 0 = user/station information
//Command 1 = shared folder list
//Command 2 = shared file transfer
sendRequest(dxcallsign, 255, 1, "1", "req");
};
}
//Send shared file request
//exports.sendRequestSharedFile = function (dxcallsign, file) {
function sendRequestSharedFile(dxcallsign, file){
function sendRequestSharedFile(dxcallsign, file) {
//Command 0 = user/station information
//Command 1 = shared folder list
//Command 2 = shared file transfer
sendRequest(dxcallsign, 255, 1, "2" + file, "req");
};
}
//Send station info response
//exports.sendResponseInfo = function (dxcallsign, userinfo) {
function sendResponseInfo(dxcallsign, userinfo){
function sendResponseInfo(dxcallsign, userinfo) {
//Command 0 = user/station information
//Command 1 = shared folder list
//Command 2 = shared file transfer
sendResponse(dxcallsign, 255, 1, userinfo, "res-0");
};
}
//Send shared folder response
//exports.sendResponseSharedFolderList = function (dxcallsign, sharedFolderList) {
function sendResponseSharedFolderList(dxcallsign, sharedFolderList){
function sendResponseSharedFolderList(dxcallsign, sharedFolderList) {
//Command 0 = user/station information
//Command 1 = shared folder list
//Command 2 = shared file transfer
sendResponse(dxcallsign, 255, 1, sharedFolderList, "res-1");
};
}
//Send shared file response
//exports.sendResponseSharedFile = function (
function sendResponseSharedFile(
dxcallsign,
sharedFile,
sharedFileData,
) {
function sendResponseSharedFile(dxcallsign, sharedFile, sharedFileData) {
console.log(
"In sendResponseSharedFile",
dxcallsign,
@ -755,62 +745,62 @@ function sendResponseSharedFile(
//Command 1 = shared folder list
//Command 2 = shared file transfer
sendResponse(dxcallsign, 255, 1, sharedFile + "/" + sharedFileData, "res-2");
};
}
//STOP TRANSMISSION
export function stopTransmission(){
export function stopTransmission() {
var command = '{"type" : "arq", "command": "stop_transmission"}';
writeTncCommand(command);
};
}
// Get RX BUffer
export function getRxBuffer(){
export function getRxBuffer() {
var command = '{"type" : "get", "command" : "rx_buffer"}';
// call command only if new data arrived
if (rxBufferLengthGui != rxBufferLengthTnc) {
writeTncCommand(command);
}
};
}
// START BEACON
export function startBeacon(interval){
export function startBeacon(interval) {
var command =
'{"type" : "broadcast", "command" : "start_beacon", "parameter": "' +
interval +
'"}';
writeTncCommand(command);
};
}
// STOP BEACON
export function stopBeacon(){
export function stopBeacon() {
var command = '{"type" : "broadcast", "command" : "stop_beacon"}';
writeTncCommand(command);
};
}
// OPEN ARQ SESSION
export function connectARQ(dxcallsign){
export function connectARQ(dxcallsign) {
command =
'{"type" : "arq", "command" : "connect", "dxcallsign": "' +
dxcallsign +
'", "attempts": "10"}';
writeTncCommand(command);
};
}
// CLOSE ARQ SESSION
export function disconnectARQ(){
export function disconnectARQ() {
var command = '{"type" : "arq", "command" : "disconnect"}';
writeTncCommand(command);
};
}
// SEND TEST FRAME
export function sendTestFrame(){
export function sendTestFrame() {
var command = '{"type" : "set", "command" : "send_test_frame"}';
writeTncCommand(command);
};
}
// SEND FEC
export function sendFEC(mode, payload){
export function sendFEC(mode, payload) {
var command =
'{"type" : "fec", "command" : "transmit", "mode" : "' +
mode +
@ -818,19 +808,19 @@ export function sendFEC(mode, payload){
payload +
'"}';
writeTncCommand(command);
};
}
// SEND FEC IS WRITING
export function sendFecIsWriting(mycallsign){
export function sendFecIsWriting(mycallsign) {
var command =
'{"type" : "fec", "command" : "transmit_is_writing", "mycallsign" : "' +
mycallsign +
'"}';
writeTncCommand(command);
};
}
// SEND FEC TO BROADCASTCHANNEL
export function sendBroadcastChannel(channel, data_out, uuid){
export function sendBroadcastChannel(channel, data_out, uuid) {
let checksum = "";
let command = "";
let data = FD.btoa_FD(
@ -851,33 +841,33 @@ export function sendBroadcastChannel(channel, data_out, uuid){
payload +
'"}';
writeTncCommand(command);
};
}
// RECORD AUDIO
export function record_audio(){
export function record_audio() {
var command = '{"type" : "set", "command" : "record_audio"}';
writeTncCommand(command);
};
}
// SET FREQUENCY
export function set_frequency(frequency){
export function set_frequency(frequency) {
var command =
'{"type" : "set", "command" : "frequency", "frequency": ' + frequency + "}";
writeTncCommand(command);
};
}
// SET MODE
export function set_mode(mode){
export function set_mode(mode) {
var command = '{"type" : "set", "command" : "mode", "mode": "' + mode + '"}';
writeTncCommand(command);
};
}
// SET rf_level
export function set_rf_level(rf_level){
var command = '{"type" : "set", "command" : "rf_level", "rf_level": "' + rf_level + '"}';
export function set_rf_level(rf_level) {
var command =
'{"type" : "set", "command" : "rf_level", "rf_level": "' + rf_level + '"}';
writeTncCommand(command);
};
}
// https://stackoverflow.com/a/50579690
// crc32 calculation
@ -895,12 +885,10 @@ var crc32 = function (r) {
return (-1 ^ n) >>> 0;
};
// TODO: Maybe moving this to another module
function prepareStatsDataForStore(data){
// dummy data
//state.arq_speed_list = [{"snr":0.0,"bpm":104,"timestamp":1696189769},{"snr":0.0,"bpm":80,"timestamp":1696189778},{"snr":0.0,"bpm":70,"timestamp":1696189783},{"snr":0.0,"bpm":58,"timestamp":1696189792},{"snr":0.0,"bpm":52,"timestamp":1696189797},{"snr":"NaN","bpm":42,"timestamp":1696189811},{"snr":0.0,"bpm":22,"timestamp":1696189875},{"snr":0.0,"bpm":21,"timestamp":1696189881},{"snr":0.0,"bpm":17,"timestamp":1696189913},{"snr":0.0,"bpm":15,"timestamp":1696189932},{"snr":0.0,"bpm":15,"timestamp":1696189937},{"snr":0.0,"bpm":14,"timestamp":1696189946},{"snr":-6.1,"bpm":14,"timestamp":1696189954},{"snr":-6.1,"bpm":14,"timestamp":1696189955},{"snr":-5.5,"bpm":28,"timestamp":1696189963},{"snr":-5.5,"bpm":27,"timestamp":1696189963}]
function prepareStatsDataForStore(data) {
// dummy data
//state.arq_speed_list = [{"snr":0.0,"bpm":104,"timestamp":1696189769},{"snr":0.0,"bpm":80,"timestamp":1696189778},{"snr":0.0,"bpm":70,"timestamp":1696189783},{"snr":0.0,"bpm":58,"timestamp":1696189792},{"snr":0.0,"bpm":52,"timestamp":1696189797},{"snr":"NaN","bpm":42,"timestamp":1696189811},{"snr":0.0,"bpm":22,"timestamp":1696189875},{"snr":0.0,"bpm":21,"timestamp":1696189881},{"snr":0.0,"bpm":17,"timestamp":1696189913},{"snr":0.0,"bpm":15,"timestamp":1696189932},{"snr":0.0,"bpm":15,"timestamp":1696189937},{"snr":0.0,"bpm":14,"timestamp":1696189946},{"snr":-6.1,"bpm":14,"timestamp":1696189954},{"snr":-6.1,"bpm":14,"timestamp":1696189955},{"snr":-5.5,"bpm":28,"timestamp":1696189963},{"snr":-5.5,"bpm":27,"timestamp":1696189963}]
if (typeof data == "undefined") {
var speed_listSize = 0;
@ -908,14 +896,13 @@ function prepareStatsDataForStore(data){
var speed_listSize = data.length;
}
var speed_list_bpm = []
var speed_list_bpm = [];
for (var i = 0; i < speed_listSize; i++) {
speed_list_bpm.push(data[i].bpm);
}
var speed_list_timestamp = []
var speed_list_timestamp = [];
for (var i = 0; i < speed_listSize; i++) {
var timestamp = data[i].timestamp * 1000;
@ -926,8 +913,7 @@ function prepareStatsDataForStore(data){
speed_list_timestamp.push(time);
}
var speed_list_snr = []
var speed_list_snr = [];
for (var i = 0; i < speed_listSize; i++) {
let snr = NaN;
if (data[i].snr !== 0) {
@ -938,8 +924,7 @@ function prepareStatsDataForStore(data){
speed_list_snr.push(snr);
}
stateStore.arq_speed_list_bpm = speed_list_bpm
stateStore.arq_speed_list_timestamp = speed_list_timestamp
stateStore.arq_speed_list_snr = speed_list_snr
stateStore.arq_speed_list_bpm = speed_list_bpm;
stateStore.arq_speed_list_timestamp = speed_list_timestamp;
stateStore.arq_speed_list_snr = speed_list_snr;
}

View file

@ -1,24 +1,24 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue';
import { defineStore } from "pinia";
import { ref, computed } from "vue";
export const useAudioStore = defineStore('audioStore', () => {
var inputDevices = ref([{"id":0, "name": "no input devices"}])
var outputDevices = ref([{"id":0, "name": "no output devices"}])
export const useAudioStore = defineStore("audioStore", () => {
var inputDevices = ref([{ id: 0, name: "no input devices" }]);
var outputDevices = ref([{ id: 0, name: "no output devices" }]);
function getInputDevices() {
var html = "";
for(var key in inputDevices.value) {
html +=`<option value=${inputDevices.value[key]["id"]}>${inputDevices.value[key]["name"]}</option>`;
for (var key in inputDevices.value) {
html += `<option value=${inputDevices.value[key]["id"]}>${inputDevices.value[key]["name"]}</option>`;
}
return html
return html;
}
function getOutputDevices() {
var html = "";
for(var key in outputDevices.value) {
html +=`<option value="${outputDevices.value[key]["id"]}">${outputDevices.value[key]["name"]}</option>`;
for (var key in outputDevices.value) {
html += `<option value="${outputDevices.value[key]["id"]}">${outputDevices.value[key]["name"]}</option>`;
}
return html
return html;
}
return { inputDevices, outputDevices, getInputDevices, getOutputDevices };

View file

@ -1,7 +1,7 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue';
import { defineStore } from "pinia";
import { ref, computed } from "vue";
export const useChatStore = defineStore('chatStore', () => {
export const useChatStore = defineStore("chatStore", () => {
var chat_filter = ref([
{ type: "newchat" },
{ type: "received" },
@ -11,31 +11,48 @@ export const useChatStore = defineStore('chatStore', () => {
{ type: "broadcast_transmit" },
//{ type: "request" },
//{ type: "response" },
])
]);
var selectedCallsign = ref();
var inputText = ref();
var inputFile = ref();
var inputFileName = ref();
var inputFileType = ref();
var inputFileSize = ref();
var selectedCallsign = ref()
var inputText = ref()
var inputFile = ref()
var inputFileName = ref()
var inputFileType = ref()
var inputFileSize = ref()
var callsign_list = ref();
var sorted_chat_list = ref();
var unsorted_chat_list = ref([]);
var callsign_list = ref()
var sorted_chat_list = ref()
var unsorted_chat_list = ref([])
var sorted_beacon_list = ref({});
var unsorted_beacon_list = ref({});
var sorted_beacon_list = ref({})
var unsorted_beacon_list = ref({})
var chartSpeedPER0 = ref();
var chartSpeedPER25 = ref();
var chartSpeedPER75 = ref();
var chartSpeedPER0 = ref()
var chartSpeedPER25 = ref()
var chartSpeedPER75 = ref()
// var beaconDataArray = ref([-3, 10, 8, 5, 3, 0, -5, 10, 8, 5, 3, 0, -5, 10, 8, 5, 3, 0, -5, 10, 8, 5, 3, 0, -5])
// var beaconLabelArray = ref(['18:10', '19:00', '23:00', '01:13', '04:25', '08:15', '09:12', '18:10', '19:00', '23:00', '01:13', '04:25', '08:15', '09:12', '18:10', '19:00', '23:00', '01:13', '04:25', '08:15', '09:12', '01:13', '04:25', '08:15', '09:12'])
var beaconDataArray = ref([]);
var beaconLabelArray = ref([]);
// var beaconDataArray = ref([-3, 10, 8, 5, 3, 0, -5, 10, 8, 5, 3, 0, -5, 10, 8, 5, 3, 0, -5, 10, 8, 5, 3, 0, -5])
// var beaconLabelArray = ref(['18:10', '19:00', '23:00', '01:13', '04:25', '08:15', '09:12', '18:10', '19:00', '23:00', '01:13', '04:25', '08:15', '09:12', '18:10', '19:00', '23:00', '01:13', '04:25', '08:15', '09:12', '01:13', '04:25', '08:15', '09:12'])
var beaconDataArray = ref([])
var beaconLabelArray = ref([])
return {selectedCallsign, inputText, chat_filter, callsign_list, sorted_chat_list, unsorted_chat_list, inputFileName, inputFileSize, inputFileType, inputFile, chartSpeedPER0, chartSpeedPER25, chartSpeedPER75, beaconDataArray, beaconLabelArray , unsorted_beacon_list, sorted_beacon_list };
return {
selectedCallsign,
inputText,
chat_filter,
callsign_list,
sorted_chat_list,
unsorted_chat_list,
inputFileName,
inputFileSize,
inputFileType,
inputFile,
chartSpeedPER0,
chartSpeedPER25,
chartSpeedPER75,
beaconDataArray,
beaconLabelArray,
unsorted_beacon_list,
sorted_beacon_list,
};
});

View file

@ -1,4 +1,4 @@
import { createPinia } from 'pinia';
import { createPinia } from "pinia";
const pinia = createPinia();

View file

@ -1,152 +1,142 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useSettingsStore = defineStore('settingsStore', () => {
import { defineStore } from "pinia";
import { ref, computed } from "vue";
export const useSettingsStore = defineStore("settingsStore", () => {
// network
var tnc_host = ref("127.0.0.1")
var tnc_port = ref(3000)
var daemon_host = ref(tnc_host.value)
var daemon_port = ref(tnc_port.value + 1)
var tnc_host = ref("127.0.0.1");
var tnc_port = ref(3000);
var daemon_host = ref(tnc_host.value);
var daemon_port = ref(tnc_port.value + 1);
// app
var screen_height = ref(430)
var screen_width = ref(1050)
var theme = ref("default")
var wftheme = ref(2)
var high_graphics = ref("False")
var auto_start = ref(0)
var enable_sys_notification = ref(1)
var screen_height = ref(430);
var screen_width = ref(1050);
var theme = ref("default");
var wftheme = ref(2);
var high_graphics = ref("False");
var auto_start = ref(0);
var enable_sys_notification = ref(1);
// chat
var shared_folder_path = ref(".")
var enable_request_profile = ref("True")
var enable_request_shared_folder = ref("False")
var max_retry_attempts = ref(5)
var enable_auto_retry = ref("False")
var shared_folder_path = ref(".");
var enable_request_profile = ref("True");
var enable_request_shared_folder = ref("False");
var max_retry_attempts = ref(5);
var enable_auto_retry = ref("False");
// station
var mycall = ref("AA0AA-5")
var myssid = ref(0)
var mygrid = ref("JN20aa")
var mycall = ref("AA0AA-5");
var myssid = ref(0);
var mygrid = ref("JN20aa");
// rigctld
var hamlib_rigctld_port = ref(4532)
var hamlib_rigctld_ip = ref("127.0.0.1")
var radiocontrol = ref("disabled")
var hamlib_deviceid = ref("RIG_MODEL_DUMMY_NOVFO")
var hamlib_deviceport = ref("ignore")
var hamlib_stop_bits = ref("ignore")
var hamlib_data_bits = ref("ignore")
var hamlib_handshake = ref("ignore")
var hamlib_serialspeed = ref("ignore")
var hamlib_dtrstate = ref("ignore")
var hamlib_pttprotocol = ref("ignore")
var hamlib_ptt_port = ref("ignore")
var hamlib_dcd = ref("ignore")
var hamlbib_serialspeed_ptt = ref(9600)
var hamlib_rigctld_port = ref(4532)
var hamlib_rigctld_ip = ref("127.0.0.1")
var hamlib_rigctld_path = ref("")
var hamlib_rigctld_server_port = ref(4532)
var hamlib_rigctld_custom_args = ref("")
var hamlib_rigctld_port = ref(4532);
var hamlib_rigctld_ip = ref("127.0.0.1");
var radiocontrol = ref("disabled");
var hamlib_deviceid = ref("RIG_MODEL_DUMMY_NOVFO");
var hamlib_deviceport = ref("ignore");
var hamlib_stop_bits = ref("ignore");
var hamlib_data_bits = ref("ignore");
var hamlib_handshake = ref("ignore");
var hamlib_serialspeed = ref("ignore");
var hamlib_dtrstate = ref("ignore");
var hamlib_pttprotocol = ref("ignore");
var hamlib_ptt_port = ref("ignore");
var hamlib_dcd = ref("ignore");
var hamlbib_serialspeed_ptt = ref(9600);
var hamlib_rigctld_port = ref(4532);
var hamlib_rigctld_ip = ref("127.0.0.1");
var hamlib_rigctld_path = ref("");
var hamlib_rigctld_server_port = ref(4532);
var hamlib_rigctld_custom_args = ref("");
// tci
var tci_ip = ref('127.0.0.1')
var tci_port = ref(50001)
var tci_ip = ref("127.0.0.1");
var tci_port = ref(50001);
//tnc
var spectrum = ref("waterfall")
var enable_scatter = ref("False")
var enable_fft = ref("False")
var enable_fsk = ref("False")
var low_bandwidth_mode = ref("False")
var update_channel = ref("latest")
var beacon_interval = ref(300)
var received_files_folder = ref("None")
var tuning_range_fmin = ref(-50.0)
var tuning_range_fmax = ref(50.0)
var respond_to_cq = ref("True")
var rx_buffer_size = ref(16)
var enable_explorer = ref("False")
var explorer_stats = ref("False")
var auto_tune = ref("False")
var enable_is_writing = ref("True")
var tx_delay = ref(0)
var enable_mesh_features = ref("False")
var spectrum = ref("waterfall");
var enable_scatter = ref("False");
var enable_fft = ref("False");
var enable_fsk = ref("False");
var low_bandwidth_mode = ref("False");
var update_channel = ref("latest");
var beacon_interval = ref(300);
var received_files_folder = ref("None");
var tuning_range_fmin = ref(-50.0);
var tuning_range_fmax = ref(50.0);
var respond_to_cq = ref("True");
var rx_buffer_size = ref(16);
var enable_explorer = ref("False");
var explorer_stats = ref("False");
var auto_tune = ref("False");
var enable_is_writing = ref("True");
var tx_delay = ref(0);
var enable_mesh_features = ref("False");
function getJSON() {
var config_export = {
tnc_host: tnc_host.value,
tnc_port: tnc_port.value,
daemon_host: tnc_host.value,
daemon_port: (parseInt(tnc_port.value) + 1).toString(),
mycall: mycall.value,
myssid: myssid.value,
mygrid: mygrid.value,
radiocontrol: radiocontrol.value,
hamlib_deviceid: hamlib_deviceid.value,
hamlib_deviceport: hamlib_deviceport.value,
hamlib_stop_bits: hamlib_stop_bits.value,
hamlib_data_bits: hamlib_data_bits.value,
hamlib_handshake: hamlib_handshake.value,
hamlib_serialspeed: hamlib_serialspeed.value,
hamlib_dtrstate: hamlib_dtrstate.value,
hamlib_pttprotocol: hamlib_pttprotocol.value,
hamlib_ptt_port: hamlib_ptt_port.value,
hamlib_dcd: hamlib_dcd.value,
hamlbib_serialspeed_ptt: hamlib_serialspeed.value,
hamlib_rigctld_port: hamlib_rigctld_port.value,
hamlib_rigctld_ip: hamlib_rigctld_ip.value,
hamlib_rigctld_path: hamlib_rigctld_path.value,
hamlib_rigctld_server_port: hamlib_rigctld_server_port.value,
hamlib_rigctld_custom_args: hamlib_rigctld_custom_args.value,
tci_port: tci_port.value,
tci_ip: tci_ip.value,
spectrum: spectrum.value,
enable_scatter: enable_scatter.value,
enable_fft: enable_fft.value,
enable_fsk: enable_fsk.value,
low_bandwidth_mode: low_bandwidth_mode.value,
theme: theme.value,
screen_height: screen_height.value,
screen_width: screen_width.value,
update_channel: update_channel.value,
beacon_interval: beacon_interval.value,
received_files_folder: received_files_folder.value,
tuning_range_fmin: tuning_range_fmin.value,
tuning_range_fmax: tuning_range_fmax.value,
respond_to_cq: respond_to_cq.value,
rx_buffer_size: rx_buffer_size.value,
enable_explorer: enable_explorer.value,
wftheme: wftheme.value,
high_graphics: high_graphics.value,
explorer_stats: explorer_stats.value,
auto_tune: auto_tune.value,
enable_is_writing: enable_is_writing.value,
shared_folder_path: shared_folder_path.value,
enable_request_profile: enable_request_profile.value,
enable_request_shared_folder: enable_request_shared_folder.value,
max_retry_attempts: max_retry_attempts.value,
enable_auto_retry: enable_auto_retry.value,
tx_delay: tx_delay.value,
auto_start: auto_start.value,
enable_sys_notification: enable_sys_notification.value,
enable_mesh_features: enable_mesh_features.value,
};
function getJSON(){
var config_export = {
"tnc_host": tnc_host.value,
"tnc_port": tnc_port.value,
"daemon_host": tnc_host.value,
"daemon_port": (parseInt(tnc_port.value) + 1).toString(),
"mycall": mycall.value,
"myssid": myssid.value,
"mygrid": mygrid.value,
"radiocontrol" : radiocontrol.value,
"hamlib_deviceid": hamlib_deviceid.value,
"hamlib_deviceport": hamlib_deviceport.value,
"hamlib_stop_bits": hamlib_stop_bits.value,
"hamlib_data_bits": hamlib_data_bits.value,
"hamlib_handshake": hamlib_handshake.value,
"hamlib_serialspeed": hamlib_serialspeed.value,
"hamlib_dtrstate": hamlib_dtrstate.value,
"hamlib_pttprotocol": hamlib_pttprotocol.value,
"hamlib_ptt_port": hamlib_ptt_port.value,
"hamlib_dcd": hamlib_dcd.value,
"hamlbib_serialspeed_ptt": hamlib_serialspeed.value,
"hamlib_rigctld_port" : hamlib_rigctld_port.value,
"hamlib_rigctld_ip" : hamlib_rigctld_ip.value,
"hamlib_rigctld_path" : hamlib_rigctld_path.value,
"hamlib_rigctld_server_port" : hamlib_rigctld_server_port.value,
"hamlib_rigctld_custom_args": hamlib_rigctld_custom_args.value,
"tci_port" : tci_port.value,
"tci_ip" : tci_ip.value,
"spectrum": spectrum.value,
"enable_scatter" : enable_scatter.value,
"enable_fft" : enable_fft.value,
"enable_fsk" : enable_fsk.value,
"low_bandwidth_mode" : low_bandwidth_mode.value,
"theme" : theme.value,
"screen_height" : screen_height.value,
"screen_width" : screen_width.value,
"update_channel" : update_channel.value,
"beacon_interval" : beacon_interval.value,
"received_files_folder" : received_files_folder.value,
"tuning_range_fmin" : tuning_range_fmin.value,
"tuning_range_fmax" : tuning_range_fmax.value,
"respond_to_cq" : respond_to_cq.value,
"rx_buffer_size" : rx_buffer_size.value,
"enable_explorer" : enable_explorer.value,
"wftheme": wftheme.value,
"high_graphics" : high_graphics.value,
"explorer_stats" : explorer_stats.value,
"auto_tune" : auto_tune.value,
"enable_is_writing" : enable_is_writing.value,
"shared_folder_path" : shared_folder_path.value,
"enable_request_profile" : enable_request_profile.value,
"enable_request_shared_folder" : enable_request_shared_folder.value,
"max_retry_attempts" : max_retry_attempts.value,
"enable_auto_retry" : enable_auto_retry.value,
"tx_delay" : tx_delay.value,
"auto_start": auto_start.value,
"enable_sys_notification": enable_sys_notification.value,
"enable_mesh_features": enable_mesh_features.value
return config_export;
}
return config_export
}
return {
tnc_host,
tnc_port,
@ -207,7 +197,5 @@ var config_export = {
tx_delay,
enable_mesh_features,
getJSON,
}
})
};
});

View file

@ -1,68 +1,62 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue';
import * as bootstrap from 'bootstrap'
import { defineStore } from "pinia";
import { ref, computed } from "vue";
import * as bootstrap from "bootstrap";
export const useStateStore = defineStore('stateStore', () => {
var busy_state = ref("-")
var arq_state = ref("-")
var frequency = ref("-")
var new_frequency = ref(0)
var mode = ref("-")
var rf_level = ref("10")
var bandwidth = ref("-")
var dbfs_level_percent = ref(0)
var dbfs_level_raw = ref(0)
export const useStateStore = defineStore("stateStore", () => {
var busy_state = ref("-");
var arq_state = ref("-");
var frequency = ref("-");
var new_frequency = ref(0);
var mode = ref("-");
var rf_level = ref("10");
var bandwidth = ref("-");
var dbfs_level_percent = ref(0);
var dbfs_level_raw = ref(0);
var ptt_state = ref("False")
var ptt_state = ref("False");
var speed_level = ref(0)
var fft = ref()
var channel_busy = ref("")
var channel_busy_slot = ref()
var scatter = ref()
var s_meter_strength_percent = ref(0)
var s_meter_strength_raw = ref(0)
var speed_level = ref(0);
var fft = ref();
var channel_busy = ref("");
var channel_busy_slot = ref();
var scatter = ref();
var s_meter_strength_percent = ref(0);
var s_meter_strength_raw = ref(0);
var tnc_connection = ref("disconnected")
var tncStartCount = ref(0)
var tnc_running_state = ref("--------")
var tnc_connection = ref("disconnected");
var tncStartCount = ref(0);
var tnc_running_state = ref("--------");
var arq_total_bytes = ref(0)
var arq_transmission_percent = ref(0)
var arq_total_bytes = ref(0);
var arq_transmission_percent = ref(0);
var heard_stations = ref("")
var dxcallsign = ref("")
var heard_stations = ref("");
var dxcallsign = ref("");
var arq_session_state = ref("")
var arq_state = ref("")
var beacon_state = ref("False")
var arq_session_state = ref("");
var arq_state = ref("");
var beacon_state = ref("False");
var audio_recording = ref("")
var audio_recording = ref("");
var hamlib_status = ref("")
var audio_level = ref("")
var alc = ref("")
var hamlib_status = ref("");
var audio_level = ref("");
var alc = ref("");
var is_codec2_traffic = ref("")
var is_codec2_traffic = ref("");
var arq_speed_list_timestamp = ref([]);
var arq_speed_list_bpm = ref([]);
var arq_speed_list_snr = ref([]);
var arq_seconds_until_finish = ref();
var arq_seconds_until_timeout = ref();
var arq_seconds_until_timeout_percent = ref();
var arq_speed_list_timestamp = ref([])
var arq_speed_list_bpm = ref([])
var arq_speed_list_snr = ref([])
var arq_seconds_until_finish = ref()
var arq_seconds_until_timeout = ref()
var arq_seconds_until_timeout_percent = ref()
function updateTncState(state){
function updateTncState(state) {
tnc_connection.value = state;
if (tnc_connection.value == "open") {
// collapse settings screen
var collapseFirstRow = new bootstrap.Collapse(
document.getElementById("collapseFirstRow"),
@ -89,9 +83,8 @@ export const useStateStore = defineStore('stateStore', () => {
//set_CPU_mode();
//GUI will auto connect to TNC if already running, if that is the case increment start count if 0
if (tncStartCount.value == 0) tncStartCount++;
if (tncStartCount.value == 0) tncStartCount.value++;
} else {
// collapse settings screen
var collapseFirstRow = new bootstrap.Collapse(
document.getElementById("collapseFirstRow"),
@ -114,13 +107,38 @@ export const useStateStore = defineStore('stateStore', () => {
);
collapseFourthRow.hide();
}
};
}
return { dxcallsign, busy_state, arq_state, new_frequency, frequency, mode, bandwidth, dbfs_level_raw, dbfs_level_percent, speed_level, fft, channel_busy, channel_busy_slot, scatter, ptt_state, s_meter_strength_percent, s_meter_strength_raw, arq_total_bytes, audio_recording, hamlib_status, audio_level, alc, updateTncState, arq_transmission_percent, arq_speed_list_bpm, arq_speed_list_timestamp, arq_speed_list_snr, arq_seconds_until_finish, arq_seconds_until_timeout, arq_seconds_until_timeout_percent };
return {
dxcallsign,
busy_state,
arq_state,
new_frequency,
frequency,
mode,
bandwidth,
dbfs_level_raw,
dbfs_level_percent,
speed_level,
fft,
channel_busy,
channel_busy_slot,
scatter,
ptt_state,
s_meter_strength_percent,
s_meter_strength_raw,
arq_total_bytes,
audio_recording,
hamlib_status,
audio_level,
alc,
updateTncState,
arq_transmission_percent,
arq_speed_list_bpm,
arq_speed_list_timestamp,
arq_speed_list_snr,
arq_seconds_until_finish,
arq_seconds_until_timeout,
arq_seconds_until_timeout_percent,
};
});