2023-09-12 15:52:16 +00:00
const path = require ( "path" ) ;
2023-09-20 04:46:37 +00:00
const { v4 : uuidv4 } = require ( "uuid" ) ;
2023-09-12 15:52:16 +00:00
// pinia store setup
2023-10-03 13:15:17 +00:00
import { setActivePinia } from "pinia" ;
import pinia from "../store/index" ;
2023-09-12 15:52:16 +00:00
setActivePinia ( pinia ) ;
2023-10-03 13:15:17 +00:00
import { useChatStore } from "../store/chatStore.js" ;
2023-09-12 15:52:16 +00:00
const chat = useChatStore ( pinia ) ;
2023-10-20 17:02:40 +00:00
import { useStateStore } from "../store/stateStore.js" ;
const state = useStateStore ( pinia ) ;
2023-11-18 16:12:05 +00:00
import { settingsStore as settings } from "../store/settingsStore.js" ;
2023-10-21 10:59:26 +00:00
2023-10-15 07:57:35 +00:00
import { displayToast } from "./popupHandler.js" ;
2023-09-20 04:46:37 +00:00
2023-10-08 07:57:03 +00:00
//const FD = require("./src/js/freedata.js");
2023-11-18 16:12:05 +00:00
import { btoa_FD , sortByProperty } from "./freedata.js" ;
2023-09-20 04:46:37 +00:00
2023-11-19 13:03:48 +00:00
import { sendModemARQRaw } from "../js/api.js" ;
const split_char = "0;1;" ;
2023-10-20 17:02:40 +00:00
// define default message object
interface Attachment {
content_type : string ;
data : string ;
}
interface messageDefaultObject {
command : string ;
hmac_signed : boolean ;
percent : number ;
bytesperminute : number ;
is_new : boolean ;
_id : string ;
timestamp : number ;
dxcallsign : string ;
dxgrid : string ;
msg : string ;
checksum : string ;
type : string ;
status : string ;
attempt : number ;
uuid : string ;
duration : number ;
nacks : number ;
speed_list : string ;
broadcast_sender? : string ; // optional for broadcasts
_attachments : {
[ filename : string ] : Attachment ;
} ;
}
2023-10-22 08:12:00 +00:00
interface beaconDefaultObject {
2023-10-20 17:02:40 +00:00
command : string ;
is_new : boolean ;
_id : string ;
timestamp : number ;
dxcallsign : string ;
dxgrid : string ;
type : string ;
status : string ;
uuid : string ;
snr : string ;
}
2023-11-04 04:13:47 +00:00
interface newChatDefaultObject {
command : string ;
is_new : boolean ;
timestamp : number ;
dxcallsign : string ;
}
2023-09-12 15:52:16 +00:00
// ---- MessageDB
try {
var PouchDB = require ( "pouchdb" ) ;
} catch ( err ) {
console . log ( err ) ;
/ *
This is a fix for raspberryPi where we get an error when loading pouchdb because of
leveldown package isnt running on ARM devices .
pouchdb - browser does not depend on leveldb and seems to be working .
* /
console . log ( "using pouchdb-browser fallback" ) ;
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
2023-10-22 08:12:00 +00:00
if ( typeof process . env [ "APPDATA" ] !== "undefined" ) {
var appDataFolder = process . env [ "APPDATA" ] ;
console . log ( appDataFolder ) ;
2023-10-08 08:33:54 +00:00
} else {
2023-10-22 08:12:00 +00:00
var appDataFolder : string ;
switch ( process . platform ) {
case "darwin" :
appDataFolder = process . env [ "HOME" ] + "/Library/Application Support" ;
console . log ( appDataFolder ) ;
break ;
case "linux" :
appDataFolder = process . env [ "HOME" ] + "/.config" ;
console . log ( appDataFolder ) ;
break ;
case "win32" :
appDataFolder = "undefined" ;
break ;
default :
appDataFolder = "undefined" ;
break ;
}
2023-10-08 08:33:54 +00:00
}
2023-10-22 08:12:00 +00:00
console . log ( "loading chat database..." ) ;
console . log ( "appdata folder:" + appDataFolder ) ;
2023-09-12 15:52:16 +00:00
var configFolder = path . join ( appDataFolder , "FreeDATA" ) ;
2023-10-22 08:12:00 +00:00
console . log ( "config folder:" + configFolder ) ;
2023-09-12 15:52:16 +00:00
var chatDB = path . join ( configFolder , "chatDB" ) ;
2023-10-22 08:12:00 +00:00
console . log ( "database path:" + chatDB ) ;
2023-10-20 18:56:52 +00:00
2023-09-12 15:52:16 +00:00
var db = new PouchDB ( chatDB ) ;
/* -------- CREATE DATABASE INDEXES */
2023-10-22 06:45:36 +00:00
//These aren't needed anylonger aslong as we await createIndex() where necessary
//createChatIndex();
2023-09-12 15:52:16 +00:00
2023-10-15 07:57:35 +00:00
/* -------- RUN A DATABASE CLEANUP ON STARTUP */
2023-10-17 13:47:30 +00:00
//dbClean()
2023-10-15 07:57:35 +00:00
2023-10-22 08:12:00 +00:00
updateAllChat ( true ) ;
2023-10-15 07:57:35 +00:00
2023-09-20 12:06:16 +00:00
// create callsign set for storing unique callsigns
2023-10-03 13:15:17 +00:00
chat . callsign_list = new Set ( ) ;
2023-09-12 15:52:16 +00:00
2023-09-27 14:55:57 +00:00
// function for creating a new broadcast
2023-10-03 13:15:17 +00:00
export function newBroadcast ( broadcastChannel , chatmessage ) {
2023-10-22 08:12:00 +00:00
var file = "" ;
var filetype = "text" ;
var filename = "" ;
2023-10-20 17:02:40 +00:00
2023-10-03 13:15:17 +00:00
var file_checksum = "" ; //crc32(file).toString(16).toUpperCase();
var message_type = "broadcast_transmit" ;
var timestamp = Math . floor ( Date . now ( ) / 1000 ) ;
var uuid = uuidv4 ( ) ;
// TODO: Not sure what this uuid part is needed for ...
let uuidlast = uuid . lastIndexOf ( "-" ) ;
uuidlast += 1 ;
if ( uuidlast > 0 ) {
uuid = uuid . substring ( uuidlast ) ;
}
// slice uuid for reducing overhead
uuid = uuid . slice ( - 4 ) ;
2023-10-22 08:12:00 +00:00
let newChatObj : messageDefaultObject = {
2023-10-22 13:52:30 +00:00
command : "broadcast" ,
2023-10-22 08:12:00 +00:00
hmac_signed : false ,
percent : 0 ,
bytesperminute : 0 , // You need to assign a value here
is_new : false ,
_id : uuid ,
timestamp : timestamp ,
dxcallsign : broadcastChannel ,
dxgrid : "null" ,
msg : chatmessage ,
checksum : file_checksum ,
type : message_type ,
status : "transmitting" ,
attempt : 1 ,
uuid : uuid ,
duration : 0 ,
nacks : 0 ,
speed_list : "null" ,
_attachments : {
[ filename ] : {
content_type : filetype ,
data : btoa_FD ( file ) ,
} ,
} ,
} ;
2023-10-03 13:15:17 +00:00
2023-10-22 08:12:00 +00:00
//sendMessage(newChatObj)
2023-12-20 02:29:53 +00:00
//sendBroadcastChannel(newChatObj);
2023-10-18 12:29:51 +00:00
2023-10-03 13:15:17 +00:00
addObjToDatabase ( newChatObj ) ;
2023-09-27 14:55:57 +00:00
}
2023-09-20 12:06:16 +00:00
// function for creating a new message
2023-10-03 13:15:17 +00:00
export function newMessage (
dxcallsign ,
chatmessage ,
chatFile ,
chatFileName ,
chatFileSize ,
chatFileType ,
) {
2023-10-20 17:02:40 +00:00
var filename = "" ;
var filetype = "" ;
2023-10-22 08:12:00 +00:00
var file = "" ;
2023-10-03 13:15:17 +00:00
if ( typeof chatFile !== "undefined" ) {
2023-10-20 17:02:40 +00:00
file = chatFile ;
filetype = chatFileType ;
filename = chatFileName ;
2023-10-03 13:15:17 +00:00
} else {
2023-10-20 17:02:40 +00:00
file = "" ;
2023-10-28 13:36:10 +00:00
filetype = "" ;
2023-10-20 17:02:40 +00:00
filename = "" ;
2023-10-03 13:15:17 +00:00
}
2023-10-28 13:36:10 +00:00
2023-10-28 13:36:29 +00:00
console . log ( file ) ;
console . log ( filetype ) ;
console . log ( filename ) ;
2023-10-28 13:36:10 +00:00
2023-10-03 13:15:17 +00:00
var file_checksum = "" ; //crc32(file).toString(16).toUpperCase();
var message_type = "transmit" ;
2023-10-22 13:44:05 +00:00
var command = "msg" ;
2023-10-03 13:15:17 +00:00
var timestamp = Math . floor ( Date . now ( ) / 1000 ) ;
var uuid = uuidv4 ( ) ;
// TODO: Not sure what this uuid part is needed for ...
let uuidlast = uuid . lastIndexOf ( "-" ) ;
uuidlast += 1 ;
if ( uuidlast > 0 ) {
uuid = uuid . substring ( uuidlast ) ;
}
// slice uuid for reducing overhead
uuid = uuid . slice ( - 8 ) ;
2023-10-22 08:12:00 +00:00
let newChatObj : messageDefaultObject = {
2023-10-22 13:44:05 +00:00
command : command ,
2023-10-22 08:12:00 +00:00
hmac_signed : false ,
percent : 0 ,
bytesperminute : 0 , // You need to assign a value here
is_new : false ,
_id : uuid ,
timestamp : timestamp ,
dxcallsign : dxcallsign ,
dxgrid : "null" ,
msg : chatmessage ,
checksum : file_checksum ,
type : message_type ,
status : "transmitting" ,
attempt : 1 ,
uuid : uuid ,
duration : 0 ,
nacks : 0 ,
speed_list : "null" ,
_attachments : {
[ filename ] : {
content_type : filetype ,
data : btoa_FD ( file ) ,
} ,
} ,
} ;
2023-09-20 04:46:37 +00:00
2023-10-18 12:29:51 +00:00
sendMessage ( newChatObj ) ;
2023-10-03 13:15:17 +00:00
addObjToDatabase ( newChatObj ) ;
2023-09-20 04:46:37 +00:00
}
2023-09-30 19:57:23 +00:00
// function for creating a list, accessible by callsign
2023-10-03 13:15:17 +00:00
function sortChatList() {
// Create an empty object to store the reordered data dynamically
var reorderedData = { } ;
var jsonObjects = chat . unsorted_chat_list ;
// Iterate through the list of JSON objects and reorder them dynamically
jsonObjects . forEach ( ( obj ) = > {
var dxcallsign = obj . dxcallsign ;
if ( dxcallsign ) {
if ( ! reorderedData [ dxcallsign ] ) {
reorderedData [ dxcallsign ] = [ ] ;
}
reorderedData [ dxcallsign ] . push ( obj ) ;
2023-10-19 03:55:24 +00:00
2023-10-22 08:12:00 +00:00
reorderedData [ dxcallsign ] = reorderedData [ dxcallsign ] . sort (
sortByProperty ( "timestamp" ) ,
) ;
2023-10-03 13:15:17 +00:00
}
} ) ;
2023-10-19 03:55:24 +00:00
//console.log(reorderedData["2LS-0"])
2023-10-03 13:15:17 +00:00
return reorderedData ;
2023-09-12 20:49:41 +00:00
}
2023-09-12 15:52:16 +00:00
2023-10-18 19:19:18 +00:00
export function getMessageAttachment ( id ) {
return new Promise ( async ( resolve , reject ) = > {
try {
const findResult = await db . find ( {
selector : {
_id : id ,
} ,
} ) ;
const getResult = await db . get ( findResult . docs [ 0 ] . _id , {
attachments : true ,
} ) ;
let obj = getResult ;
let filename = Object . keys ( obj . _attachments ) [ 0 ] ;
let filetype = obj . _attachments [ filename ] . content_type ;
let file = obj . _attachments [ filename ] . data ;
resolve ( [ filename , filetype , file ] ) ;
} catch ( err ) {
console . log ( err ) ;
reject ( false ) ; // Reject the Promise if there's an error
}
} ) ;
}
2023-09-22 21:21:44 +00:00
//repeat a message
2023-10-03 13:15:17 +00:00
export function repeatMessageTransmission ( id ) {
2023-10-14 13:32:30 +00:00
// 1. get message object by ID
// 2. Upsert Attempts
// 3. send message
2023-10-18 12:29:51 +00:00
2023-10-22 08:12:00 +00:00
db . find ( {
2023-10-18 12:29:51 +00:00
selector : {
_id : id ,
} ,
2023-10-22 08:12:00 +00:00
} )
. then ( function ( result ) {
console . log ( result ) ;
let obj = result . docs [ 0 ] ;
console . log ( obj ) ;
obj . attempt += 1 ;
databaseUpsert ( obj . uuid , "attempt" , obj . attempt ) ;
updateUnsortedChatListEntry ( obj . uuid , "attempt" , obj . attempt ) ;
sendMessage ( obj ) ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
2023-09-22 21:21:44 +00:00
}
// delete a message from databse and gui
2023-10-03 13:15:17 +00:00
export function deleteMessageFromDB ( id ) {
console . log ( "deleting: " + id ) ;
db . get ( id ) . then ( function ( 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 ,
) ;
// 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 ( ) ;
2023-09-22 21:21:44 +00:00
}
2023-09-12 15:52:16 +00:00
2023-10-15 07:57:35 +00:00
//Function to clean old beacons and optimize database
async function dbClean() {
//Only keep the most x latest days of beacons
let beaconKeep = 4 ;
let itemCount = 0 ;
let timestampPurge = Math . floor (
( Date . now ( ) - beaconKeep * 24 * 60 * 60 * 1000 ) / 1000 ,
) ;
//Items to purge from database
var purgeFilter = [
{ type : "beacon" } ,
{ type : "ping-ack" } ,
{ type : "ping" } ,
2023-10-18 11:45:57 +00:00
{ type : "request" } ,
{ type : "response" } ,
2023-10-15 07:57:35 +00:00
] ;
await db
. find ( {
selector : {
$and : [ { timestamp : { $lt : timestampPurge } } , { $or : purgeFilter } ] ,
} ,
} )
. then ( async function ( result ) {
//console.log("Purging " + result.docs.length + " beacons received before " + timestampPurge);
itemCount = result . docs . length ;
result . docs . forEach ( async function ( item ) {
2023-10-22 08:12:00 +00:00
await deleteMessageFromDB ( item . _id ) ;
2023-10-15 07:57:35 +00:00
} ) ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
//Compact database
2023-10-22 06:45:36 +00:00
//Too slow on older/slower machines
//await db.compact();
2023-10-15 07:57:35 +00:00
2023-12-20 02:29:53 +00:00
let message = "Database maintenance is complete, " ;
//displayToast("info", "bi bi-info-circle", message, 5000);
2023-10-17 13:47:30 +00:00
2023-12-20 02:29:53 +00:00
message += "removed " + itemCount + " items from database" ;
console . log ( message ) ;
2023-10-15 07:57:35 +00:00
}
2023-10-02 07:50:52 +00:00
// function to update transmission status
2023-10-03 13:15:17 +00:00
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 ) ;
// update screen rendering / messages
updateUnsortedChatListEntry ( obj . uuid , "percent" , obj . percent ) ;
updateUnsortedChatListEntry ( obj . uuid , "bytesperminute" , obj . bytesperminute ) ;
updateUnsortedChatListEntry ( obj . uuid , "status" , obj . status ) ;
2023-10-02 07:50:52 +00:00
}
2023-10-03 13:15:17 +00:00
export function updateUnsortedChatListEntry ( uuid , object , value ) {
2023-10-22 08:12:00 +00:00
var data = getFromUnsortedChatListByUUID ( uuid ) ;
if ( data ) {
2023-10-14 13:32:30 +00:00
data [ object ] = value ;
2023-12-20 02:29:53 +00:00
//console.log("Entry updated:", data[object]);
2023-10-14 13:32:30 +00:00
chat . sorted_chat_list = sortChatList ( ) ;
return data ;
}
/ *
2023-10-03 13:15:17 +00:00
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 ;
2023-10-02 07:50:52 +00:00
}
2023-10-03 13:15:17 +00:00
}
2023-10-14 13:32:30 +00:00
* /
2023-10-02 07:50:52 +00:00
2023-12-20 02:29:53 +00:00
//console.log("Entry not updated:", object);
2023-10-03 13:15:17 +00:00
return null ; // Return null if not found
2023-10-02 07:50:52 +00:00
}
2023-10-22 08:12:00 +00:00
function getFromUnsortedChatListByUUID ( uuid ) {
for ( const entry of chat . unsorted_chat_list ) {
if ( entry . uuid === uuid ) {
return entry ;
2023-10-14 13:32:30 +00:00
}
2023-10-22 08:12:00 +00:00
}
return false ;
}
export function getNewMessagesByDXCallsign ( dxcallsign ) : [ number , number , any ] {
let new_counter = 0 ;
let total_counter = 0 ;
let item_array = [ ] ;
2023-11-03 21:12:27 +00:00
try {
if (
typeof dxcallsign !== "undefined" &&
typeof chat . sorted_chat_list [ dxcallsign ] !== "undefined"
) {
for ( const key in chat . sorted_chat_list [ dxcallsign ] ) {
//console.log(chat.sorted_chat_list[dxcallsign][key])
//item_array.push(chat.sorted_chat_list[dxcallsign][key])
if ( chat . sorted_chat_list [ dxcallsign ] [ key ] . is_new ) {
item_array . push ( chat . sorted_chat_list [ dxcallsign ] [ key ] ) ;
new_counter += 1 ;
2023-11-03 21:08:29 +00:00
}
2023-11-03 21:12:27 +00:00
total_counter += 1 ;
2023-10-18 11:45:57 +00:00
}
2023-11-03 21:12:27 +00:00
}
2023-10-18 11:45:57 +00:00
2023-11-03 21:12:27 +00:00
return [ total_counter , new_counter , item_array ] ;
} catch ( e ) {
console . log ( e ) ;
return [ 0 , 0 , item_array ] ;
2023-11-03 21:08:29 +00:00
}
2023-10-18 11:45:57 +00:00
}
2023-10-22 08:12:00 +00:00
export function resetIsNewMessage ( uuid , value ) {
databaseUpsert ( uuid , "is_new" , value ) ;
updateUnsortedChatListEntry ( uuid , "is_new" , value ) ;
2023-10-18 11:45:57 +00:00
}
2023-10-03 13:15:17 +00:00
export function databaseUpsert ( id , object , value ) {
db . upsert ( id , function ( doc ) {
if ( ! doc [ object ] ) {
2023-10-02 07:50:52 +00:00
doc [ object ] = value ;
2023-10-03 13:15:17 +00:00
}
doc [ object ] = value ;
return doc ;
} )
. then ( function ( res ) {
2023-10-02 07:50:52 +00:00
// success, res is {rev: '1-xxx', updated: true, id: 'myDocId'}
2023-12-20 02:29:53 +00:00
//console.log(res);
2023-10-03 13:15:17 +00:00
} )
. catch ( function ( err ) {
2023-10-02 07:50:52 +00:00
// error
2023-10-03 13:15:17 +00:00
console . log ( err ) ;
2023-10-02 07:50:52 +00:00
} ) ;
}
2023-09-20 12:06:16 +00:00
// function for fetching all messages from chat / updating chat
2023-10-17 13:47:30 +00:00
export async function updateAllChat ( cleanup ) {
2023-10-22 08:12:00 +00:00
// run cleanup if requested
if ( cleanup ) {
await dbClean ( ) ;
}
let indexFields = [ { dxcallsign : "asc" } , { timestamp : "asc" } ] ;
2023-10-21 11:05:50 +00:00
let filter = {
2023-10-22 08:12:00 +00:00
selector : {
$and : [
{ dxcallsign : { $exists : true } } ,
{ timestamp : { $exists : true } } ,
//{ $or: chat.chat_filter },
] ,
} ,
sort : [ { dxcallsign : "asc" } , { timestamp : "asc" } ] ,
} ;
//"{ dxcallsign: \"asc\" }, { timestamp: \"asc\" }"
await createIndex ( indexFields ) ;
getFromDBByFilter ( filter )
. then ( function ( result ) {
for ( var item of ( result as any ) . docs ) {
const dxcallsign = item . dxcallsign ;
// Check if dxcallsign already exists as a property in the result object
if ( ! chat . sorted_beacon_list [ dxcallsign ] ) {
// If not, initialize it with an empty array for snr values
chat . sorted_beacon_list [ dxcallsign ] = {
dxcallsign ,
snr : [ ] ,
timestamp : [ ] ,
} ;
chat . callsign_list . add ( dxcallsign ) ;
2023-10-21 11:05:50 +00:00
}
2023-09-12 15:52:16 +00:00
2023-10-22 08:12:00 +00:00
if ( item . type === "beacon" ) {
//console.log(item);
// TODO: sort beacon list .... maybe a part for a separate function
const jsonData = [ item ] ;
// Process each JSON item step by step
jsonData . forEach ( ( jsonitem ) = > {
const { snr , timestamp } = item ;
2023-10-21 11:05:50 +00:00
2023-10-22 08:12:00 +00:00
// 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 . unsorted_chat_list . push ( item ) ;
chat . sorted_chat_list = sortChatList ( ) ;
2023-10-26 09:55:57 +00:00
// check if message is expired
let timeNow = Math . floor ( Date . now ( ) / 1000 ) ;
2023-10-26 10:12:53 +00:00
let expireTimestamp = timeNow - 10 * 60 ;
let isExpired = false ;
if ( expireTimestamp >= item . timestamp ) {
isExpired = true ;
2023-10-26 09:55:57 +00:00
}
2023-10-26 10:12:53 +00:00
if ( item . status == "transmitting" && isExpired ) {
console . log ( "message expired - resetting status" ) ;
console . log ( item ) ;
2023-10-26 09:55:57 +00:00
databaseUpsert ( item . uuid , "status" , "failed" ) ;
updateUnsortedChatListEntry ( item . uuid , "status" , "failed" ) ;
2023-10-28 13:36:10 +00:00
databaseUpsert ( item . uuid , "percent" , 0 ) ;
updateUnsortedChatListEntry ( item . uuid , "percent" , 0 ) ;
}
// lets update the message if it is failed. Then its always 0 percent
if ( item . status == "failed" ) {
databaseUpsert ( item . uuid , "percent" , 0 ) ;
updateUnsortedChatListEntry ( item . uuid , "percent" , 0 ) ;
databaseUpsert ( item . uuid , "bytesperminute" , 0 ) ;
updateUnsortedChatListEntry ( item . uuid , "bytesperminute" , 0 ) ;
2023-10-26 09:55:57 +00:00
}
2023-10-22 08:12:00 +00:00
}
}
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
2023-09-12 15:52:16 +00:00
}
2023-10-03 13:15:17 +00:00
function addObjToDatabase ( newobj ) {
console . log ( newobj ) ;
/ *
2023-09-20 04:46:37 +00:00
db . upsert ( newobj . _id , function ( doc ) {
if ( ! doc . _id ) {
console . log ( "upsert" )
console . log ( doc )
doc = newobj
} else {
console . log ( "new..." )
* /
2023-10-03 13:15:17 +00:00
db . post ( newobj )
. then ( function ( response ) {
// handle response
console . log ( "new database entry" ) ;
console . log ( response ) ;
2023-10-11 18:39:35 +00:00
2023-11-18 16:12:05 +00:00
if ( newobj . command === "msg" || newobj . command === "newchat" ) {
2023-10-11 18:39:35 +00:00
chat . unsorted_chat_list . push ( newobj ) ;
chat . sorted_chat_list = sortChatList ( ) ;
}
2023-10-03 13:15:17 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
2023-10-11 18:39:35 +00:00
console . log ( newobj ) ;
// try upserting status in case we tried sending a message to our selfes
databaseUpsert ( newobj . uuid , "status" , newobj . status ) ;
updateUnsortedChatListEntry ( newobj . uuid , "status" , newobj . status ) ;
2023-10-03 13:15:17 +00:00
} ) ;
2023-09-20 04:46:37 +00:00
2023-10-03 13:15:17 +00:00
/ *
2023-09-20 04:46:37 +00:00
// upsert footer ...
}
return doc ;
} )
* /
}
2023-10-22 13:44:05 +00:00
/ *
2023-09-12 15:52:16 +00:00
function createChatIndex() {
db . createIndex ( {
index : {
fields : [
"timestamp" ,
"uuid" ,
"dxcallsign" ,
"dxgrid" ,
"msg" ,
"checksum" ,
"type" ,
"command" ,
"status" ,
"percent" ,
"attempt" ,
"hmac_signed" ,
"bytesperminute" ,
"_attachments" ,
2023-09-20 04:46:37 +00:00
"is_new" ,
2023-10-11 18:39:35 +00:00
"nacks" ,
"duration" ,
2023-10-22 08:12:00 +00:00
"speed_list" ,
2023-09-12 15:52:16 +00:00
] ,
} ,
} )
. then ( function ( result ) {
// handle result
console . log ( result ) ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
}
2023-10-22 13:44:05 +00:00
* /
2023-09-14 19:45:07 +00:00
2023-10-03 13:15:17 +00:00
export function deleteChatByCallsign ( callsign ) {
chat . callsign_list . delete ( callsign ) ;
2023-10-20 17:02:40 +00:00
// @ts-expect-error
2023-10-03 13:15:17 +00:00
delete chat . unsorted_chat_list . callsign ;
delete chat . sorted_chat_list . callsign ;
2023-09-14 19:45:07 +00:00
2023-10-03 13:15:17 +00:00
deleteFromDatabaseByCallsign ( callsign ) ;
2023-09-14 19:45:07 +00:00
}
2023-10-03 13:15:17 +00:00
function deleteFromDatabaseByCallsign ( callsign ) {
db . find ( {
selector : {
dxcallsign : callsign ,
} ,
} )
. then ( function ( result ) {
// handle result
if ( typeof result !== "undefined" ) {
result . docs . forEach ( function ( item ) {
console . log ( item ) ;
db . get ( item . _id )
. then ( function ( doc ) {
db . remove ( doc )
2023-10-22 13:44:05 +00:00
. then ( function ( ) {
2023-10-23 13:01:04 +00:00
//updateAllChat(false);
2023-10-03 13:15:17 +00:00
return true ;
2023-09-14 19:45:07 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
2023-10-03 13:15:17 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
2023-09-14 19:45:07 +00:00
} ) ;
} ) ;
2023-10-03 13:15:17 +00:00
}
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
2023-09-20 04:46:37 +00:00
}
2023-11-04 18:55:18 +00:00
//Function creates a new 'newchat' database entry when user initates a new chat, otherwise cannot send messages unless receiving a message/beacon from user first
/ * *
* Add a newuser to the database , for when newuser button is clicked
* @param { string } call callsign of new user
2023-11-18 16:12:05 +00:00
* /
2023-11-04 18:55:18 +00:00
export function startChatWithNewStation ( call ) {
2023-11-04 04:13:47 +00:00
let newchat : newChatDefaultObject = {
2023-11-18 16:12:05 +00:00
command : "newchat" ,
is_new : false ,
timestamp : Math.floor ( new Date ( ) . getTime ( ) / 1000 ) ,
dxcallsign : call ,
2023-11-04 04:13:47 +00:00
} ;
2023-11-18 16:12:05 +00:00
addObjToDatabase ( newchat ) ;
if ( ! chat . sorted_beacon_list [ call ] ) {
// If not, initialize it with an empty array for snr values
chat . sorted_beacon_list [ call ] = {
call ,
snr : [ ] ,
timestamp : [ ] ,
} ;
chat . callsign_list . add ( call ) ;
}
//chat.unsorted_chat_list.push(newchat);
//chat.sorted_chat_list = sortChatList();
2023-11-04 04:13:47 +00:00
}
2023-09-30 18:30:19 +00:00
// function for handling a received beacon
2023-10-03 13:15:17 +00:00
export function newBeaconReceived ( obj ) {
/ *
2023-09-30 18:30:19 +00:00
{
2023-10-20 11:47:42 +00:00
"freedata" : "modem-message" ,
2023-09-30 18:30:19 +00:00
"beacon" : "received" ,
"uuid" : "12741312-3dbb-4a53-b0cc-100f6c930ab8" ,
"timestamp" : 1696076869 ,
"dxcallsign" : "DJ2LS-0" ,
"dxgrid" : "JN48CS" ,
"snr" : "-2.8" ,
"mycallsign" : "DJ2LS-0"
}
* /
2023-10-22 08:12:00 +00:00
let newChatObj : beaconDefaultObject = {
command : "beacon" ,
is_new : false ,
_id : obj [ "uuid" ] ,
timestamp : obj [ "timestamp" ] ,
dxcallsign : obj [ "dxcallsign" ] ,
dxgrid : obj [ "dxgrid" ] ,
type : "beacon" ,
status : obj [ "beacon" ] ,
uuid : obj [ "uuid" ] ,
snr : obj [ "snr" ] , // adding the new field
} ;
2023-10-20 17:02:40 +00:00
2023-10-03 13:15:17 +00:00
addObjToDatabase ( newChatObj ) ;
console . log ( obj ) ;
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
if ( ! chat . sorted_beacon_list [ dxcallsign ] ) {
// If not, initialize it with an empty array for snr values
chat . sorted_beacon_list [ dxcallsign ] = {
dxcallsign ,
snr : [ ] ,
timestamp : [ ] ,
} ;
}
2023-10-01 11:24:54 +00:00
2023-10-03 13:15:17 +00:00
// 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 ) ;
} ) ;
2023-10-21 10:59:26 +00:00
// check if auto retry enabled
2023-12-20 02:29:53 +00:00
//console.log("-----------------------------------------");
//console.log(settings.enable_auto_retry.toUpperCase());
//if (settings.enable_auto_retry.toUpperCase() == "TRUE") {
// checkForWaitingMessages(dxcallsign);
//}
2023-09-30 18:30:19 +00:00
}
2023-09-20 12:06:16 +00:00
// function for handling a received message
2023-10-03 13:15:17 +00:00
export function newMessageReceived ( message , protocol ) {
/ *
2023-09-27 14:55:57 +00:00
PROTOCOL
2023-10-11 18:26:44 +00:00
{
2023-10-20 11:47:42 +00:00
"freedata" : "modem-message" ,
2023-10-11 18:26:44 +00:00
"arq" : "transmission" ,
"status" : "received" ,
"uuid" : "5a3caa57-7feb-4436-853d-e341b085350f" ,
"percent" : 100 ,
"bytesperminute" : 206 ,
"compression" : 0.5833333333333334 ,
"timestamp" : 1697048385 ,
"finished" : 0 ,
"mycallsign" : "DJ2LS-0" ,
"dxcallsign" : "DJ2LS-0" ,
"dxgrid" : "------" ,
"data" : "bTA7MTttc2cwOzE7MDsxOzBlNGE3YjQ2MDsxOzE2OTcwNDgzMTkwOzE7dGVzdDMwOzE7MDsxO3RleHQwOzE7" ,
"irs" : "False" ,
"hmac_signed" : "False" ,
"duration" : 44.385897636413574 ,
"nacks" : 1 ,
"speed_list" : [
{
"snr" : 0 ,
"bpm" : 106 ,
"timestamp" : 1697048362
} ,
{
"snr" : - 6 ,
"bpm" : 104 ,
"timestamp" : 1697048370
} ,
{
"snr" : - 6 ,
"bpm" : 81 ,
"timestamp" : 1697048370
} ,
{
"snr" : - 5.7 ,
"bpm" : 161 ,
"timestamp" : 1697048378
} ,
{
"snr" : - 5.7 ,
"bpm" : 133 ,
"timestamp" : 1697048379
} ,
{
"snr" : - 5.4 ,
"bpm" : 206 ,
"timestamp" : 1697048385
} ,
{
"snr" : - 5.8 ,
"bpm" : 179 ,
"timestamp" : 1697048391
}
]
}
2023-09-20 12:06:16 +00:00
2023-09-27 14:55:57 +00:00
MESSAGE ; decoded from "data"
[
0 - protocol type message - "m" ,
1 - type - "msg" ,
2 - checksum "" ,
3 - uuid - "07e2" ,
4 - timestamp - "1695203833" ,
5 - message - "test" ,
6 - file name - "" ,
7 - mime - "plain/text" ,
8 - file - ""
]
2023-09-20 12:06:16 +00:00
2023-09-27 14:55:57 +00:00
* /
2023-10-03 13:15:17 +00:00
console . log ( protocol ) ;
2023-10-22 08:12:00 +00:00
let newChatObj : messageDefaultObject = {
command : "msg" ,
hmac_signed : protocol [ "hmac_signed" ] ,
percent : 100 ,
bytesperminute : protocol [ "bytesperminute" ] ,
is_new : true ,
_id : message [ 3 ] ,
timestamp : message [ 4 ] ,
dxcallsign : protocol [ "dxcallsign" ] ,
dxgrid : protocol [ "dxgrid" ] ,
msg : message [ 5 ] ,
checksum : message [ 2 ] ,
type : protocol [ "status" ] ,
status : protocol [ "status" ] ,
attempt : 1 ,
uuid : message [ 3 ] ,
duration : protocol [ "duration" ] ,
nacks : protocol [ "nacks" ] ,
speed_list : protocol [ "speed_list" ] ,
_attachments : {
[ message [ 6 ] ] : {
content_type : message [ 7 ] ,
data : btoa_FD ( message [ 8 ] ) ,
} ,
} ,
} ;
2023-09-20 12:06:16 +00:00
2023-10-03 13:15:17 +00:00
// some tweaks for broadcasts
if ( protocol . fec == "broadcast" ) {
newChatObj . broadcast_sender = protocol [ "dxcallsign" ] ;
newChatObj . type = "broadcast_received" ;
}
2023-09-20 12:06:16 +00:00
2023-10-03 13:15:17 +00:00
addObjToDatabase ( newChatObj ) ;
2023-09-20 12:06:16 +00:00
}
2023-10-03 13:15:17 +00:00
export function setStateFailed() {
state . arq_seconds_until_finish = 0 ;
state . arq_seconds_until_timeout = 180 ;
state . arq_seconds_until_timeout_percent = 100 ;
2023-10-02 18:50:24 +00:00
}
2023-10-03 13:15:17 +00:00
export function setStateSuccess() {
state . arq_seconds_until_finish = 0 ;
state . arq_seconds_until_timeout = 180 ;
state . arq_seconds_until_timeout_percent = 100 ;
2023-10-02 18:50:24 +00:00
}
2023-09-20 12:06:16 +00:00
2023-10-22 08:12:00 +00:00
export function requestMessageInfo ( id ) {
console . log ( id ) ;
2023-10-22 12:49:33 +00:00
chat . arq_speed_list_bpm = [ ] ;
chat . arq_speed_list_timestamp = [ ] ;
chat . arq_speed_list_snr = [ ] ;
2023-10-22 13:52:30 +00:00
//@ts-expect-error
2023-10-22 12:49:33 +00:00
chat . selectedMessageObject = [ ] ;
2023-10-22 08:12:00 +00:00
// id and uuid are the same
var data = getFromUnsortedChatListByUUID ( id ) ;
chat . selectedMessageObject = data ;
2023-10-28 13:36:29 +00:00
console . log ( data ) ;
2023-10-22 12:51:07 +00:00
if (
typeof data [ "speed_list" ] !== "undefined" &&
data [ "speed_list" ] . length > 0
) {
prepareStatsDataForStore ( data [ "speed_list" ] ) ;
} else {
prepareStatsDataForStore ( [ { } ] ) ;
}
2023-10-22 12:49:33 +00:00
2023-10-22 12:51:07 +00:00
return ;
2023-10-22 12:49:33 +00:00
}
// THis is a nearly duplicate of the same function in sock.js :-(
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}]
2023-10-22 12:51:07 +00:00
console . log ( data ) ;
console . log ( ) ;
var speed_listSize = 0 ;
2023-10-22 12:49:33 +00:00
if ( typeof data == "undefined" ) {
speed_listSize = 0 ;
} else {
speed_listSize = data . length ;
}
var speed_list_bpm = [ ] ;
for ( let i = 0 ; i < speed_listSize ; i ++ ) {
speed_list_bpm . push ( data [ i ] . bpm ) ;
}
var speed_list_timestamp = [ ] ;
for ( let i = 0 ; i < speed_listSize ; i ++ ) {
let timestamp = data [ i ] . timestamp * 1000 ;
let h = new Date ( timestamp ) . getHours ( ) ;
let m = new Date ( timestamp ) . getMinutes ( ) ;
let s = new Date ( timestamp ) . getSeconds ( ) ;
let time = h + ":" + m + ":" + s ;
speed_list_timestamp . push ( time ) ;
}
var speed_list_snr = [ ] ;
for ( let i = 0 ; i < speed_listSize ; i ++ ) {
let snr = NaN ;
if ( data [ i ] . snr !== 0 ) {
snr = data [ i ] . snr ;
} else {
snr = NaN ;
}
speed_list_snr . push ( snr ) ;
}
chat . arq_speed_list_bpm = speed_list_bpm ;
chat . arq_speed_list_timestamp = speed_list_timestamp ;
chat . arq_speed_list_snr = speed_list_snr ;
2023-10-22 12:51:07 +00:00
return ;
2023-10-21 10:59:26 +00:00
}
2023-10-22 08:12:00 +00:00
async function createIndex ( myIndexFields ) {
db . createIndex ( {
index : {
fields : myIndexFields ,
} ,
} ) . catch ( ( err ) = > {
console . log ( err ) ;
} ) ;
2023-10-22 06:45:36 +00:00
}
2023-10-22 08:12:00 +00:00
async function getFromDBByFilter ( filter ) {
/ *
2023-10-21 10:59:26 +00:00
USAGE :
let filter = {
selector : {
dxcallsign : dxcall ,
type : "transmit" ,
status : "failed" ,
//attempt: { $lt: parseInt(config.max_retry_attempts) }
} ,
}
getFromDBByFilter ( filter )
. then ( result = > {
console . log ( result )
} )
. catch ( err = > {
console . log ( err )
} ) ;
* /
2023-10-22 08:12:00 +00:00
return new Promise ( ( resolve , reject ) = > {
return db
. find ( filter )
. then ( ( result ) = > {
2023-10-22 12:49:33 +00:00
//console.log(result);
2023-10-22 08:12:00 +00:00
resolve ( result ) ;
} )
. catch ( ( err ) = > {
console . log ( err ) ;
reject ( err ) ;
} ) ;
} ) ;
2023-10-21 10:59:26 +00:00
}
async function checkForWaitingMessages ( dxcall ) {
2023-10-22 08:12:00 +00:00
let filter = {
2023-10-21 10:59:26 +00:00
selector : {
dxcallsign : dxcall ,
type : "transmit" ,
status : "failed" ,
//attempt: { $lt: parseInt(config.max_retry_attempts) }
} ,
2023-10-22 08:12:00 +00:00
} ;
2023-10-21 10:59:26 +00:00
2023-10-22 08:12:00 +00:00
getFromDBByFilter ( filter )
. then ( ( result ) = > {
let message =
2023-10-22 08:15:23 +00:00
// @ts-expect-error
2023-10-22 08:12:00 +00:00
"Found " + result . docs . length + " waiting messages for " + dxcall ;
2023-10-21 11:34:26 +00:00
2023-10-22 08:12:00 +00:00
console . log ( message ) ;
displayToast ( "info" , "bi bi-info-circle" , message , 5000 ) ;
2023-10-28 13:14:47 +00:00
console . log ( result ) ;
2023-10-28 17:27:20 +00:00
// @ts-expect-error
2023-10-28 13:14:47 +00:00
console . log ( result . docs ) ;
2023-10-28 17:27:20 +00:00
// @ts-expect-error
2023-10-28 13:14:47 +00:00
console . log ( result . docs . length ) ;
2023-10-21 10:59:26 +00:00
// handle result
2023-10-21 11:34:26 +00:00
// @ts-expect-error
2023-10-21 10:59:26 +00:00
if ( result . docs . length > 0 ) {
// only want to process the first available item object, then return
// this ensures, we are only sending one message at once
2023-10-28 17:27:20 +00:00
// @ts-expect-error
2023-10-28 13:14:47 +00:00
console . log ( result . docs [ 0 ] ) ;
2023-12-20 02:29:53 +00:00
//console.log(
// "attempt: " +
// result.docs[0].attempt +
// "/" +
// settings.max_retry_attempts,
//);
2023-10-22 08:12:00 +00:00
// @ts-expect-error
2023-10-21 11:34:26 +00:00
if ( result . docs [ 0 ] . attempt < settings . max_retry_attempts ) {
2023-10-28 13:14:47 +00:00
console . log ( "repeating message..." ) ;
2023-10-22 08:12:00 +00:00
// @ts-expect-error
repeatMessageTransmission ( result . docs [ 0 ] . uuid ) ;
2023-10-21 10:59:26 +00:00
}
return ;
}
2023-10-22 08:12:00 +00:00
} )
. catch ( ( err ) = > {
console . log ( err ) ;
} ) ;
}
2023-11-19 13:03:48 +00:00
export function sendMessage ( obj ) {
let dxcallsign = obj . dxcallsign ;
let checksum = obj . checksum ;
let uuid = obj . uuid ;
let command = obj . command ;
let filename = Object . keys ( obj . _attachments ) [ 0 ] ;
//let filetype = filename.split(".")[1]
let filetype = obj . _attachments [ filename ] . content_type ;
let file = obj . _attachments [ filename ] . data ;
let data_with_attachment =
obj . timestamp +
split_char +
obj . msg +
split_char +
filename +
split_char +
filetype +
split_char +
file ;
let data = btoa_FD (
"m" +
split_char +
command +
split_char +
checksum +
split_char +
uuid +
split_char +
data_with_attachment ,
) ;
2023-11-19 13:04:10 +00:00
let mycallsign =
settings . remote . STATION . mycall + "-" + settings . remote . STATION . myssid ;
sendModemARQRaw ( mycallsign , dxcallsign , data , uuid ) ;
}