mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
Merge pull request #673 from DJ2LS/dev-nsis-installer
NSIS Installer for Windows
This commit is contained in:
commit
9520bb4689
26 changed files with 413 additions and 675 deletions
|
@ -14,6 +14,15 @@ jobs:
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
|
|
||||||
|
- name: Electron Builder
|
||||||
|
working-directory: gui
|
||||||
|
run: |
|
||||||
|
npm i
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
- name: LIST ALL FILES
|
||||||
|
run: ls -R
|
||||||
|
|
||||||
- name: Install Python dependencies
|
- name: Install Python dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
|
@ -36,9 +45,9 @@ jobs:
|
||||||
run: ls -R
|
run: ls -R
|
||||||
|
|
||||||
- name: Create installer
|
- name: Create installer
|
||||||
uses: joncloud/makensis-action@v4
|
uses: joncloud/makensis-action@v4.1
|
||||||
with:
|
with:
|
||||||
script-file: "freedata-server-nsis-config.nsi"
|
script-file: "freedata-nsis-config.nsi"
|
||||||
arguments: '/V3'
|
arguments: '/V3'
|
||||||
|
|
||||||
- name: LIST ALL FILES
|
- name: LIST ALL FILES
|
||||||
|
@ -47,12 +56,14 @@ jobs:
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: 'FreeData-Server-Installer'
|
name: 'FreeDATA-Installer'
|
||||||
path: ./FreeData-Server-Installer.exe
|
path: ./FreeDATA-Installer.exe
|
||||||
|
|
||||||
- name: Upload Installer to Release
|
- name: Upload Installer to Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
files: ./FreeData-Server-Installer.exe
|
files: ./FreeDATA-Installer.exe
|
||||||
|
tag_name: ${{ github.ref_name }}
|
||||||
|
name: 'FreeDATA-Installer-${{ github.ref_name }}'
|
2
.github/workflows/build_server.yml
vendored
2
.github/workflows/build_server.yml
vendored
|
@ -48,7 +48,7 @@ jobs:
|
||||||
brew install portaudio
|
brew install portaudio
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip3 install pyaudio
|
pip3 install pyaudio
|
||||||
export PYTHONPATH=/opt/homebrew/opt/portaudio/lib/:$PYTHONPATH
|
export PYTHONPATH=/usr/local/lib/:$PYTHONPATH
|
||||||
|
|
||||||
- name: Install Python dependencies
|
- name: Install Python dependencies
|
||||||
run: |
|
run: |
|
||||||
|
|
132
freedata-nsis-config.nsi
Normal file
132
freedata-nsis-config.nsi
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
!include "MUI2.nsh"
|
||||||
|
|
||||||
|
; Request administrative rights
|
||||||
|
RequestExecutionLevel admin
|
||||||
|
|
||||||
|
; The name and file name of the installer
|
||||||
|
Name "FreeDATA Installer"
|
||||||
|
OutFile "FreeDATA-Installer.exe"
|
||||||
|
|
||||||
|
; Default installation directory for the server
|
||||||
|
InstallDir "$LOCALAPPDATA\FreeDATA"
|
||||||
|
|
||||||
|
; Registry key to store the installation directory
|
||||||
|
InstallDirRegKey HKCU "Software\FreeDATA" "Install_Dir"
|
||||||
|
|
||||||
|
; Modern UI settings
|
||||||
|
!define MUI_ABORTWARNING
|
||||||
|
|
||||||
|
; Installer interface settings
|
||||||
|
!define MUI_ICON "documentation\icon.ico"
|
||||||
|
!define MUI_UNICON "documentation\icon.ico" ; Icon for the uninstaller
|
||||||
|
|
||||||
|
; Define the welcome page text
|
||||||
|
!define MUI_WELCOMEPAGE_TEXT "Welcome to the FreeDATA Setup Wizard. This wizard will guide you through the installation process."
|
||||||
|
!define MUI_FINISHPAGE_TEXT "Folder: $INSTDIR"
|
||||||
|
!define MUI_DIRECTORYPAGE_TEXT_TOP "Please select the installation folder. It's recommended to use the suggested one to avoid permission problems."
|
||||||
|
|
||||||
|
; Pages
|
||||||
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
|
!insertmacro MUI_PAGE_LICENSE "LICENSE"
|
||||||
|
!insertmacro MUI_PAGE_COMPONENTS
|
||||||
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
|
!insertmacro MUI_PAGE_FINISH
|
||||||
|
|
||||||
|
; Uninstaller
|
||||||
|
!insertmacro MUI_UNPAGE_WELCOME
|
||||||
|
!insertmacro MUI_UNPAGE_CONFIRM
|
||||||
|
!insertmacro MUI_UNPAGE_INSTFILES
|
||||||
|
!insertmacro MUI_UNPAGE_FINISH
|
||||||
|
|
||||||
|
; Language (you can choose and configure the language(s) you want)
|
||||||
|
!insertmacro MUI_LANGUAGE "English"
|
||||||
|
|
||||||
|
|
||||||
|
; Installer Sections
|
||||||
|
Section "FreeData Server" SEC01
|
||||||
|
; Set output path to the installation directory
|
||||||
|
SetOutPath $INSTDIR\freedata-server
|
||||||
|
|
||||||
|
; Check if "config.ini" exists and back it up
|
||||||
|
IfFileExists $INSTDIR\freedata-server\config.ini backupConfig
|
||||||
|
|
||||||
|
doneBackup:
|
||||||
|
; Add your application files here
|
||||||
|
File /r "modem\server.dist\*"
|
||||||
|
|
||||||
|
; Restore the original "config.ini" if it was backed up
|
||||||
|
IfFileExists $INSTDIR\freedata-server\config.ini.bak restoreConfig
|
||||||
|
|
||||||
|
; Create a shortcut in the user's desktop
|
||||||
|
CreateShortCut "$DESKTOP\FreeDATA Server.lnk" "$INSTDIR\freedata-server\freedata-server.exe"
|
||||||
|
|
||||||
|
; Create Uninstaller
|
||||||
|
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
|
; Create a Start Menu directory
|
||||||
|
CreateDirectory "$SMPROGRAMS\FreeDATA"
|
||||||
|
|
||||||
|
; Create shortcut in the Start Menu directory
|
||||||
|
CreateShortCut "$SMPROGRAMS\FreeDATA\FreeDATA Server.lnk" "$INSTDIR\freedata-server\freedata-server.exe"
|
||||||
|
|
||||||
|
; Create an Uninstall shortcut
|
||||||
|
CreateShortCut "$SMPROGRAMS\FreeDATA\Uninstall FreeDATA.lnk" "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
|
|
||||||
|
; Backup "config.ini" before overwriting files
|
||||||
|
backupConfig:
|
||||||
|
Rename $INSTDIR\freedata-server\config.ini $INSTDIR\freedata-server\config.ini.bak
|
||||||
|
Goto doneBackup
|
||||||
|
|
||||||
|
; Restore the original "config.ini"
|
||||||
|
restoreConfig:
|
||||||
|
Delete $INSTDIR\freedata-server\config.ini
|
||||||
|
Rename $INSTDIR\freedata-server\config.ini.bak $INSTDIR\freedata-server\config.ini
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "FreeData x64 GUI" SEC02
|
||||||
|
; Set output path to the GUI installation directory
|
||||||
|
SetOutPath $INSTDIR\freedata-gui
|
||||||
|
|
||||||
|
; Add GUI files here
|
||||||
|
File /r "gui\release\win-unpacked\*"
|
||||||
|
|
||||||
|
; Create a shortcut on the desktop for the GUI
|
||||||
|
CreateShortCut "$DESKTOP\FreeDATA GUI.lnk" "$INSTDIR\freedata-gui\freedata.exe"
|
||||||
|
|
||||||
|
; Create a start menu shortcut
|
||||||
|
CreateShortCut "$SMPROGRAMS\FreeDATA\FreeDATA GUI.lnk" "$INSTDIR\freedata-gui\freedata.exe"
|
||||||
|
|
||||||
|
; Create an Uninstall shortcut
|
||||||
|
CreateShortCut "$SMPROGRAMS\FreeDATA\Uninstall FreeDATA.lnk" "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
; Uninstaller Section
|
||||||
|
Section "Uninstall"
|
||||||
|
; Delete files and directories for the server
|
||||||
|
Delete $INSTDIR\freedata-server\*.*
|
||||||
|
RMDir /r $INSTDIR\freedata-server
|
||||||
|
|
||||||
|
; Delete files and directories for the GUI
|
||||||
|
Delete $INSTDIR\freedata-gui\*.*
|
||||||
|
RMDir /r $INSTDIR\freedata-gui
|
||||||
|
|
||||||
|
; Remove the desktop shortcuts
|
||||||
|
Delete "$DESKTOP\FreeDATA Server.lnk"
|
||||||
|
Delete "$DESKTOP\FreeDATA GUI.lnk"
|
||||||
|
|
||||||
|
; Remove Start Menu shortcuts
|
||||||
|
Delete "$SMPROGRAMS\FreeDATA\*.*"
|
||||||
|
RMDir "$SMPROGRAMS\FreeDATA"
|
||||||
|
|
||||||
|
; Attempt to delete the uninstaller itself
|
||||||
|
Delete $EXEPATH
|
||||||
|
|
||||||
|
; Now remove the installation directory if it's empty
|
||||||
|
RMDir /r $INSTDIR
|
||||||
|
SectionEnd
|
|
@ -1,102 +0,0 @@
|
||||||
!include "MUI2.nsh"
|
|
||||||
|
|
||||||
; Request administrative rights
|
|
||||||
RequestExecutionLevel admin
|
|
||||||
|
|
||||||
; The name and file name of the installer
|
|
||||||
Name "FreeData Server"
|
|
||||||
OutFile "FreeData-Server-Installer.exe"
|
|
||||||
|
|
||||||
; Default installation directory
|
|
||||||
; InstallDir "$PROGRAMFILES\FreeData\freedata-server"
|
|
||||||
|
|
||||||
InstallDir "$LOCALAPPDATA\FreeData\freedata-server"
|
|
||||||
|
|
||||||
; Registry key to store the installation directory
|
|
||||||
InstallDirRegKey HKCU "Software\FreeData\freedata-server" "Install_Dir"
|
|
||||||
|
|
||||||
; Modern UI settings
|
|
||||||
!define MUI_ABORTWARNING
|
|
||||||
|
|
||||||
; Installer interface settings
|
|
||||||
!define MUI_ICON "documentation\icon.ico"
|
|
||||||
!define MUI_UNICON "documentation\icon.ico" ; Icon for the uninstaller
|
|
||||||
|
|
||||||
|
|
||||||
; Define the welcome page text
|
|
||||||
!define MUI_WELCOMEPAGE_TEXT "Welcome to the FreeData Server Setup Wizard. This wizard will guide you through the installation process."
|
|
||||||
!define MUI_FINISHPAGE_TEXT "Folder: $INSTDIR"
|
|
||||||
|
|
||||||
|
|
||||||
!define MUI_DIRECTORYPAGE_TEXT_TOP "Please select the installation folder. Its recommended using the suggested one for avoiding permission problems."
|
|
||||||
|
|
||||||
|
|
||||||
; Pages
|
|
||||||
!insertmacro MUI_PAGE_WELCOME
|
|
||||||
!insertmacro MUI_PAGE_LICENSE "LICENSE"
|
|
||||||
;!insertmacro MUI_PAGE_COMPONENTS
|
|
||||||
!insertmacro MUI_PAGE_DIRECTORY
|
|
||||||
!insertmacro MUI_PAGE_INSTFILES
|
|
||||||
!insertmacro MUI_PAGE_FINISH
|
|
||||||
|
|
||||||
; Uninstaller
|
|
||||||
!insertmacro MUI_UNPAGE_WELCOME
|
|
||||||
!insertmacro MUI_UNPAGE_CONFIRM
|
|
||||||
!insertmacro MUI_UNPAGE_INSTFILES
|
|
||||||
!insertmacro MUI_UNPAGE_FINISH
|
|
||||||
|
|
||||||
; Language (you can choose and configure the language(s) you want)
|
|
||||||
!insertmacro MUI_LANGUAGE "English"
|
|
||||||
|
|
||||||
; Installer Sections
|
|
||||||
Section "FreeData Server" SEC01
|
|
||||||
|
|
||||||
; Set output path to the installation directory
|
|
||||||
SetOutPath $INSTDIR
|
|
||||||
|
|
||||||
; Check if "config.ini" exists and back it up
|
|
||||||
IfFileExists $INSTDIR\config.ini backupConfig
|
|
||||||
|
|
||||||
doneBackup:
|
|
||||||
; Add your application files here
|
|
||||||
File /r "modem\server.dist\*.*"
|
|
||||||
|
|
||||||
; Restore the original "config.ini" if it was backed up
|
|
||||||
IfFileExists $INSTDIR\config.ini.bak restoreConfig
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; Create a shortcut in the user's desktop
|
|
||||||
CreateShortCut "$DESKTOP\FreeData Server.lnk" "$INSTDIR\freedata-server.exe"
|
|
||||||
|
|
||||||
; Create Uninstaller
|
|
||||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
|
||||||
|
|
||||||
; Backup "config.ini" before overwriting files
|
|
||||||
backupConfig:
|
|
||||||
Rename $INSTDIR\config.ini $INSTDIR\config.ini.bak
|
|
||||||
Goto doneBackup
|
|
||||||
|
|
||||||
; Restore the original "config.ini"
|
|
||||||
restoreConfig:
|
|
||||||
Delete $INSTDIR\config.ini
|
|
||||||
Rename $INSTDIR\config.ini.bak $INSTDIR\config.ini
|
|
||||||
|
|
||||||
|
|
||||||
SectionEnd
|
|
||||||
|
|
||||||
; Uninstaller Section
|
|
||||||
Section "Uninstall"
|
|
||||||
|
|
||||||
; Delete files and directories
|
|
||||||
Delete $INSTDIR\freedata-server.exe
|
|
||||||
RMDir /r $INSTDIR
|
|
||||||
|
|
||||||
; Remove the shortcut
|
|
||||||
Delete "$DESKTOP\FreeData Server.lnk"
|
|
||||||
|
|
||||||
; Additional uninstallation commands here
|
|
||||||
|
|
||||||
SectionEnd
|
|
||||||
|
|
||||||
|
|
|
@ -45,18 +45,12 @@
|
||||||
"icon": "build/icon.png",
|
"icon": "build/icon.png",
|
||||||
"target": [
|
"target": [
|
||||||
{
|
{
|
||||||
"target": "nsis",
|
"target": "portable",
|
||||||
"arch": ["arm64", "x64"]
|
"arch": ["arm64", "x64"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"artifactName": "${productName}-GUI-Windows-${version}.${ext}"
|
"artifactName": "${productName}-GUI-Windows-${version}.${ext}"
|
||||||
},
|
},
|
||||||
"nsis": {
|
|
||||||
"oneClick": false,
|
|
||||||
"perMachine": false,
|
|
||||||
"allowToChangeInstallationDirectory": true,
|
|
||||||
"deleteAppDataOnUninstall": true
|
|
||||||
},
|
|
||||||
"linux": {
|
"linux": {
|
||||||
"category": "Development",
|
"category": "Development",
|
||||||
"target": [
|
"target": [
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { app, BrowserWindow, shell, ipcMain } from "electron";
|
import { app, BrowserWindow, shell, ipcMain } from "electron";
|
||||||
import { release, platform } from "node:os";
|
import { release, platform } from "os";
|
||||||
import { join } from "node:path";
|
import { join, dirname } from "path";
|
||||||
import { autoUpdater } from "electron-updater";
|
|
||||||
import { existsSync } from "fs";
|
import { existsSync } from "fs";
|
||||||
import { spawn } from "child_process";
|
import { spawn } from "child_process";
|
||||||
|
|
||||||
|
@ -20,7 +19,6 @@ process.env.DIST = join(process.env.DIST_ELECTRON, "../dist");
|
||||||
process.env.VITE_PUBLIC = process.env.VITE_DEV_SERVER_URL
|
process.env.VITE_PUBLIC = process.env.VITE_DEV_SERVER_URL
|
||||||
? join(process.env.DIST_ELECTRON, "../public")
|
? join(process.env.DIST_ELECTRON, "../public")
|
||||||
: process.env.DIST;
|
: process.env.DIST;
|
||||||
process.env.FDUpdateAvail = "0";
|
|
||||||
|
|
||||||
// Disable GPU Acceleration for Windows 7
|
// Disable GPU Acceleration for Windows 7
|
||||||
if (release().startsWith("6.1")) app.disableHardwareAcceleration();
|
if (release().startsWith("6.1")) app.disableHardwareAcceleration();
|
||||||
|
@ -40,7 +38,7 @@ if (!app.requestSingleInstanceLock()) {
|
||||||
// process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
|
// process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
|
||||||
|
|
||||||
// set daemon process var
|
// set daemon process var
|
||||||
var daemonProcess = null;
|
var serverProcess = null;
|
||||||
let win: BrowserWindow | null = null;
|
let win: BrowserWindow | null = null;
|
||||||
// Here, you can also use other preload
|
// Here, you can also use other preload
|
||||||
const preload = join(__dirname, "../preload/index.js");
|
const preload = join(__dirname, "../preload/index.js");
|
||||||
|
@ -75,9 +73,9 @@ async function createWindow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test actively push message to the Electron-Renderer
|
// Test actively push message to the Electron-Renderer
|
||||||
win.webContents.on("did-finish-load", () => {
|
//win.webContents.on("did-finish-load", () => {
|
||||||
win?.webContents.send("main-process-message", new Date().toLocaleString());
|
// win?.webContents.send("main-process-message", new Date().toLocaleString());
|
||||||
});
|
//});
|
||||||
|
|
||||||
// Make all links open with the browser, not with the application
|
// Make all links open with the browser, not with the application
|
||||||
win.webContents.setWindowOpenHandler(({ url }) => {
|
win.webContents.setWindowOpenHandler(({ url }) => {
|
||||||
|
@ -87,12 +85,7 @@ async function createWindow() {
|
||||||
// win.webContents.on('will-navigate', (event, url) => { }) #344
|
// win.webContents.on('will-navigate', (event, url) => { }) #344
|
||||||
|
|
||||||
win.once("ready-to-show", () => {
|
win.once("ready-to-show", () => {
|
||||||
//autoUpdater.logger = log.scope("updater");
|
//
|
||||||
//autoUpdater.channel = config.update_channel;
|
|
||||||
autoUpdater.autoInstallOnAppQuit = false;
|
|
||||||
autoUpdater.autoDownload = true;
|
|
||||||
autoUpdater.checkForUpdatesAndNotify();
|
|
||||||
//autoUpdater.quitAndInstall();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,68 +95,61 @@ app.whenReady().then(() => {
|
||||||
|
|
||||||
console.log(platform());
|
console.log(platform());
|
||||||
//Generate daemon binary path
|
//Generate daemon binary path
|
||||||
var daemonPath = "";
|
var serverPath = "";
|
||||||
|
console.log(process.env);
|
||||||
|
|
||||||
|
// Attempt to find Installation Folder
|
||||||
|
console.log(app.getAppPath());
|
||||||
|
console.log(join(app.getAppPath(), "..", ".."));
|
||||||
|
console.log(join(app.getAppPath(), "..", "..", ".."));
|
||||||
|
|
||||||
|
//var basePath = join(app.getAppPath(), '..', '..', '..') || join(process.env.PWD, '..') || join(process.env.INIT_CWD, '..') || join(process.env.DIST, '..', '..', '..');
|
||||||
|
var basePath = join(app.getAppPath(), "..", "..", "..");
|
||||||
switch (platform().toLowerCase()) {
|
switch (platform().toLowerCase()) {
|
||||||
case "darwin":
|
//case "darwin":
|
||||||
daemonPath = join(process.resourcesPath, "modem", "freedata-server");
|
//serverPath = join(basePath, "freedata-server", "freedata-server.exe");
|
||||||
case "linux":
|
//serverProcess = spawn(serverPath, [], { detached: true });
|
||||||
daemonPath = join(process.resourcesPath, "modem", "freedata-server");
|
//serverProcess.unref(); // Allow the server process to continue running independently of the parent process
|
||||||
break;
|
// break;
|
||||||
|
//case "linux":
|
||||||
|
//serverPath = join(basePath, "freedata-server", "freedata-server.exe");
|
||||||
|
//serverProcess = spawn(serverPath, [], { detached: true });
|
||||||
|
//serverProcess.unref(); // Allow the server process to continue running independently of the parent process
|
||||||
|
// break;
|
||||||
case "win32":
|
case "win32":
|
||||||
daemonPath = join(process.resourcesPath, "modem", "freedata-server.exe");
|
serverPath = join(basePath, "freedata-server", "freedata-server.exe");
|
||||||
break;
|
console.log(`Starting server with path: ${serverPath}`);
|
||||||
case "win64":
|
serverProcess = spawn(
|
||||||
daemonPath = join(process.resourcesPath, "modem", "freedata-server.exe");
|
"cmd.exe",
|
||||||
|
["/c", "start", "cmd.exe", "/c", serverPath],
|
||||||
|
{ shell: true },
|
||||||
|
);
|
||||||
|
console.log(`Started server | PID: ${serverProcess.pid}`);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.log("Unhandled OS Platform: ", platform());
|
console.log("Unhandled OS Platform: ", platform());
|
||||||
|
serverProcess = null;
|
||||||
|
serverPath = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Start daemon binary if it exists
|
serverProcess.on("error", (err) => {
|
||||||
if (existsSync(daemonPath)) {
|
console.error("Failed to start server process:", err);
|
||||||
console.log("Starting freedata-server binary");
|
serverProcess = null;
|
||||||
console.log("daemonPath:", daemonPath);
|
serverPath = null;
|
||||||
console.log("CWD:", join(daemonPath, ".."));
|
});
|
||||||
/*
|
serverProcess.stdout.on("data", (data) => {
|
||||||
var daemonProcess = spawn("freedata-server", [], {
|
//console.log(`stdout: ${data}`);
|
||||||
cwd: join(process.env.DIST, "modem"),
|
});
|
||||||
shell: true
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
daemonProcess = spawn(daemonPath, [], {
|
|
||||||
shell: true
|
|
||||||
});
|
|
||||||
console.log(daemonProcess)
|
|
||||||
*/
|
|
||||||
daemonProcess = spawn(daemonPath, [], {});
|
|
||||||
|
|
||||||
// return process messages
|
serverProcess.stderr.on("data", (data) => {
|
||||||
daemonProcess.on("error", (err) => {
|
console.error(`stderr: ${data}`);
|
||||||
//daemonProcessLog.error(`error when starting daemon: ${err}`);
|
});
|
||||||
console.log(err);
|
});
|
||||||
});
|
|
||||||
daemonProcess.on("message", () => {
|
|
||||||
// daemonProcessLog.info(`${data}`);
|
|
||||||
});
|
|
||||||
daemonProcess.stdout.on("data", () => {
|
|
||||||
// daemonProcessLog.info(`${data}`);
|
|
||||||
});
|
|
||||||
daemonProcess.stderr.on("data", (data) => {
|
|
||||||
// daemonProcessLog.info(`${data}`);
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
daemonProcess.on("close", (code) => {
|
|
||||||
// daemonProcessLog.warn(`daemonProcess exited with code ${code}`);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
daemonProcess = null;
|
|
||||||
daemonPath = null;
|
|
||||||
console.log("Daemon binary doesn't exist--normal for dev environments.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//)
|
app.on("before-quit", () => {
|
||||||
|
close_sub_processes();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on("window-all-closed", () => {
|
app.on("window-all-closed", () => {
|
||||||
|
@ -205,104 +191,33 @@ ipcMain.handle("open-win", (_, arg) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//restart and install udpate
|
|
||||||
ipcMain.on("request-restart-and-install-update", (event, data) => {
|
|
||||||
close_sub_processes();
|
|
||||||
autoUpdater.quitAndInstall();
|
|
||||||
});
|
|
||||||
|
|
||||||
// LISTENER FOR UPDATER EVENTS
|
|
||||||
autoUpdater.on("update-available", (info) => {
|
|
||||||
process.env.FDUpdateAvail = "1";
|
|
||||||
console.log("update available");
|
|
||||||
|
|
||||||
let arg = {
|
|
||||||
status: "update-available",
|
|
||||||
info: info,
|
|
||||||
};
|
|
||||||
win.webContents.send("action-updater", arg);
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on("update-not-available", (info) => {
|
|
||||||
console.log("update not available");
|
|
||||||
let arg = {
|
|
||||||
status: "update-not-available",
|
|
||||||
info: info,
|
|
||||||
};
|
|
||||||
win.webContents.send("action-updater", arg);
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on("update-downloaded", (info) => {
|
|
||||||
process.env.FDUpdateAvail = "1";
|
|
||||||
console.log("update downloaded");
|
|
||||||
let arg = {
|
|
||||||
status: "update-downloaded",
|
|
||||||
info: info,
|
|
||||||
};
|
|
||||||
win.webContents.send("action-updater", arg);
|
|
||||||
// we need to call this at this point.
|
|
||||||
// if an update is available and we are force closing the app
|
|
||||||
// the entire screen crashes...
|
|
||||||
//console.log('quit application and install update');
|
|
||||||
//autoUpdater.quitAndInstall();
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on("checking-for-update", () => {
|
|
||||||
console.log("checking for update");
|
|
||||||
let arg = {
|
|
||||||
status: "checking-for-update",
|
|
||||||
version: app.getVersion(),
|
|
||||||
};
|
|
||||||
win.webContents.send("action-updater", arg);
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on("download-progress", (progress) => {
|
|
||||||
let arg = {
|
|
||||||
status: "download-progress",
|
|
||||||
progress: progress,
|
|
||||||
};
|
|
||||||
win.webContents.send("action-updater", arg);
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on("error", (error) => {
|
|
||||||
console.log("update error");
|
|
||||||
let arg = {
|
|
||||||
status: "error",
|
|
||||||
progress: error,
|
|
||||||
};
|
|
||||||
win.webContents.send("action-updater", arg);
|
|
||||||
console.log("AUTO UPDATER : " + error);
|
|
||||||
});
|
|
||||||
|
|
||||||
function close_sub_processes() {
|
function close_sub_processes() {
|
||||||
console.log("closing sub processes");
|
console.log("Closing sub processes...");
|
||||||
|
|
||||||
// closing the modem binary if not closed when closing application and also our daemon which has been started by the gui
|
if (serverProcess != null) {
|
||||||
try {
|
try {
|
||||||
if (daemonProcess != null) {
|
console.log(`Killing server process with PID: ${serverProcess.pid}`);
|
||||||
daemonProcess.kill();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("closing modem and daemon");
|
switch (platform().toLowerCase()) {
|
||||||
try {
|
//case "darwin":
|
||||||
if (platform() == "win32") {
|
// process.kill(serverProcess.pid);
|
||||||
spawn("Taskkill", ["/IM", "freedata-modem.exe", "/F"]);
|
// break;
|
||||||
spawn("Taskkill", ["/IM", "freedata-server.exe", "/F"]);
|
//case "linux":
|
||||||
}
|
// process.kill(serverProcess.pid);
|
||||||
|
// break;
|
||||||
|
case "win32":
|
||||||
|
// For Windows, use taskkill to ensure all child processes are also terminated
|
||||||
|
spawn("taskkill", ["/pid", serverProcess.pid.toString(), "/f", "/t"]);
|
||||||
|
break;
|
||||||
|
|
||||||
if (platform() == "linux") {
|
default:
|
||||||
spawn("pkill", ["-9", "freedata-modem"]);
|
console.log("Unhandled OS Platform: ", platform());
|
||||||
spawn("pkill", ["-9", "freedata-server"]);
|
serverProcess = null;
|
||||||
|
serverPath = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error killing server process: ${error}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (platform() == "darwin") {
|
|
||||||
spawn("pkill", ["-9", "freedata-modem"]);
|
|
||||||
spawn("pkill", ["-9", "freedata-server"]);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,83 +111,4 @@ window.onmessage = (ev) => {
|
||||||
ev.data.payload === "removeLoading" && removeLoading();
|
ev.data.payload === "removeLoading" && removeLoading();
|
||||||
};
|
};
|
||||||
|
|
||||||
setTimeout(removeLoading, 4999);
|
setTimeout(removeLoading, 3999);
|
||||||
|
|
||||||
// IPC ACTION FOR AUTO UPDATER
|
|
||||||
ipcRenderer.on("action-updater", (event, arg) => {
|
|
||||||
if (arg.status == "download-progress") {
|
|
||||||
var progressinfo =
|
|
||||||
"(" +
|
|
||||||
Math.round(arg.progress.transferred / 1024) +
|
|
||||||
"kB /" +
|
|
||||||
Math.round(arg.progress.total / 1024) +
|
|
||||||
"kB)" +
|
|
||||||
" @ " +
|
|
||||||
Math.round(arg.progress.bytesPerSecond / 1024) +
|
|
||||||
"kByte/s";
|
|
||||||
document.getElementById("UpdateProgressInfo").innerHTML = progressinfo;
|
|
||||||
|
|
||||||
document
|
|
||||||
.getElementById("UpdateProgressBar")
|
|
||||||
.setAttribute("aria-valuenow", arg.progress.percent);
|
|
||||||
document
|
|
||||||
.getElementById("UpdateProgressBar")
|
|
||||||
.setAttribute("style", "width:" + arg.progress.percent + "%;");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg.status == "checking-for-update") {
|
|
||||||
//document.title = document.title + ' - v' + arg.version;
|
|
||||||
//updateTitle(
|
|
||||||
// config.myCall,
|
|
||||||
// config.tnc_host,
|
|
||||||
// config.tnc_port,
|
|
||||||
// " -v " + arg.version,
|
|
||||||
//);
|
|
||||||
document.getElementById("updater_status").innerHTML =
|
|
||||||
'<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>';
|
|
||||||
|
|
||||||
document.getElementById("updater_status").className =
|
|
||||||
"btn btn-secondary btn-sm";
|
|
||||||
document.getElementById("update_and_install").style.display = "none";
|
|
||||||
}
|
|
||||||
if (arg.status == "update-downloaded") {
|
|
||||||
document.getElementById("update_and_install").removeAttribute("style");
|
|
||||||
document.getElementById("updater_status").innerHTML =
|
|
||||||
'<i class="bi bi-cloud-download ms-1 me-1" style="color: white;"></i>';
|
|
||||||
document.getElementById("updater_status").className =
|
|
||||||
"btn btn-success btn-sm";
|
|
||||||
|
|
||||||
// HERE WE NEED TO RUN THIS SOMEHOW...
|
|
||||||
//mainLog.info('quit application and install update');
|
|
||||||
//autoUpdater.quitAndInstall();
|
|
||||||
}
|
|
||||||
if (arg.status == "update-not-available") {
|
|
||||||
document.getElementById("updater_last_version").innerHTML =
|
|
||||||
arg.info.releaseName;
|
|
||||||
document.getElementById("updater_last_update").innerHTML =
|
|
||||||
arg.info.releaseDate;
|
|
||||||
document.getElementById("updater_release_notes").innerHTML =
|
|
||||||
arg.info.releaseNotes;
|
|
||||||
|
|
||||||
document.getElementById("updater_status").innerHTML =
|
|
||||||
'<i class="bi bi-check2-square ms-1 me-1" style="color: white;"></i>';
|
|
||||||
document.getElementById("updater_status").className =
|
|
||||||
"btn btn-success btn-sm";
|
|
||||||
document.getElementById("update_and_install").style.display = "none";
|
|
||||||
}
|
|
||||||
if (arg.status == "update-available") {
|
|
||||||
document.getElementById("updater_status").innerHTML =
|
|
||||||
'<i class="bi bi-hourglass-split ms-1 me-1" style="color: white;"></i>';
|
|
||||||
document.getElementById("updater_status").className =
|
|
||||||
"btn btn-warning btn-sm";
|
|
||||||
document.getElementById("update_and_install").style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg.status == "error") {
|
|
||||||
document.getElementById("updater_status").innerHTML =
|
|
||||||
'<i class="bi bi-exclamation-square ms-1 me-1" style="color: white;"></i>';
|
|
||||||
document.getElementById("updater_status").className =
|
|
||||||
"btn btn-danger btn-sm";
|
|
||||||
document.getElementById("update_and_install").style.display = "none";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
"release": "vue-tsc --noEmit && vite build && electron-builder -p onTag",
|
"release": "vue-tsc --noEmit && vite build && electron-builder -p onTag",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"lint": "eslint --ext .js,.vue src",
|
"lint": "eslint --ext .js,.vue src",
|
||||||
"lint-fix": "eslint --ext .js,.vue --fix src"
|
"lint-fix": "eslint --ext .js,.vue --fix src",
|
||||||
|
"install-deps": "npm install && npm update"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -21,15 +21,13 @@ import main_modem_healthcheck from "./main_modem_healthcheck.vue";
|
||||||
import Dynamic_components from "./dynamic_components.vue";
|
import Dynamic_components from "./dynamic_components.vue";
|
||||||
|
|
||||||
import { getFreedataMessages } from "../js/api";
|
import { getFreedataMessages } from "../js/api";
|
||||||
|
import { getRemote } from "../store/settingsStore.js";
|
||||||
|
import { loadAllData } from "../js/eventHandler";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!-------------------------------- INFO TOASTS ---------------->
|
<!-------------------------------- INFO TOASTS ---------------->
|
||||||
<div
|
<div aria-live="polite" aria-atomic="true" class="position-relative z-3">
|
||||||
aria-live="polite"
|
|
||||||
aria-atomic="true"
|
|
||||||
class="position-relative z-3"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="toast-container position-absolute top-0 end-0 p-3"
|
class="toast-container position-absolute top-0 end-0 p-3"
|
||||||
id="mainToastContainer"
|
id="mainToastContainer"
|
||||||
|
@ -47,6 +45,7 @@ import { getFreedataMessages } from "../js/api";
|
||||||
id="main-list-tab"
|
id="main-list-tab"
|
||||||
role="tablist"
|
role="tablist"
|
||||||
style="margin-top: 100px"
|
style="margin-top: 100px"
|
||||||
|
@click="loadAllData"
|
||||||
>
|
>
|
||||||
<main_modem_healthcheck />
|
<main_modem_healthcheck />
|
||||||
|
|
||||||
|
@ -111,6 +110,7 @@ import { getFreedataMessages } from "../js/api";
|
||||||
role="tab"
|
role="tab"
|
||||||
aria-controls="list-settings"
|
aria-controls="list-settings"
|
||||||
title="Settings"
|
title="Settings"
|
||||||
|
@click="loadAllData"
|
||||||
><i class="bi bi-gear-wide-connected h3"></i
|
><i class="bi bi-gear-wide-connected h3"></i
|
||||||
></a>
|
></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
import { Modal } from "bootstrap";
|
import { Modal } from "bootstrap";
|
||||||
import { onMounted } from "vue";
|
import { onMounted } from "vue";
|
||||||
|
|
||||||
import settings_updater_core from "./settings_updater_core.vue";
|
|
||||||
|
|
||||||
import { setActivePinia } from "pinia";
|
import { setActivePinia } from "pinia";
|
||||||
import pinia from "../store/index";
|
import pinia from "../store/index";
|
||||||
setActivePinia(pinia);
|
setActivePinia(pinia);
|
||||||
|
@ -14,6 +12,11 @@ import { sendModemCQ } from "../js/api.js";
|
||||||
import { useStateStore } from "../store/stateStore.js";
|
import { useStateStore } from "../store/stateStore.js";
|
||||||
const state = useStateStore(pinia);
|
const state = useStateStore(pinia);
|
||||||
|
|
||||||
|
import { useAudioStore } from "../store/audioStore";
|
||||||
|
const audioStore = useAudioStore();
|
||||||
|
import { useSerialStore } from "../store/serialStore";
|
||||||
|
const serialStore = useSerialStore();
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getVersion,
|
getVersion,
|
||||||
setConfig,
|
setConfig,
|
||||||
|
@ -21,11 +24,8 @@ import {
|
||||||
stopModem,
|
stopModem,
|
||||||
getModemState,
|
getModemState,
|
||||||
} from "../js/api";
|
} from "../js/api";
|
||||||
import { audioInputOptions, audioOutputOptions } from "../js/deviceFormHelper";
|
|
||||||
import { serialDeviceOptions } from "../js/deviceFormHelper";
|
|
||||||
|
|
||||||
const version = import.meta.env.PACKAGE_VERSION;
|
const version = import.meta.env.PACKAGE_VERSION;
|
||||||
var updateAvailable = process.env.FDUpdateAvail;
|
|
||||||
|
|
||||||
// start modemCheck modal once on startup
|
// start modemCheck modal once on startup
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -203,6 +203,7 @@ function testHamlib() {
|
||||||
</button>
|
</button>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Audio Input Device -->
|
<!-- Audio Input Device -->
|
||||||
<div class="input-group input-group-sm mb-1">
|
<div class="input-group input-group-sm mb-1">
|
||||||
<label class="input-group-text w-50"
|
<label class="input-group-text w-50"
|
||||||
|
@ -215,10 +216,10 @@ function testHamlib() {
|
||||||
v-model="settings.remote.AUDIO.input_device"
|
v-model="settings.remote.AUDIO.input_device"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
v-for="option in audioInputOptions()"
|
v-for="device in audioStore.audioInputs"
|
||||||
v-bind:value="option.id"
|
:value="device.id"
|
||||||
>
|
>
|
||||||
{{ option.name }} [{{ option.api }}]
|
{{ device.name }} [{{ device.api }}]
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -235,10 +236,10 @@ function testHamlib() {
|
||||||
v-model="settings.remote.AUDIO.output_device"
|
v-model="settings.remote.AUDIO.output_device"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
v-for="option in audioOutputOptions()"
|
v-for="device in audioStore.audioOutputs"
|
||||||
v-bind:value="option.id"
|
:value="device.id"
|
||||||
>
|
>
|
||||||
{{ option.name }} [{{ option.api }}]
|
{{ device.name }} [{{ device.api }}]
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -310,18 +311,16 @@ function testHamlib() {
|
||||||
>
|
>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
class="form-select form-select-sm"
|
|
||||||
aria-label=".form-select-sm"
|
|
||||||
id="hamlib_deviceport"
|
|
||||||
style="width: 7rem"
|
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
v-model="settings.remote.RADIO.serial_port"
|
v-model="settings.remote.RADIO.serial_port"
|
||||||
|
class="form-select form-select-sm"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
v-for="option in serialDeviceOptions()"
|
v-for="device in serialStore.serialDevices"
|
||||||
v-bind:value="option.port"
|
:value="device.port"
|
||||||
|
:key="device.port"
|
||||||
>
|
>
|
||||||
{{ option.description }}
|
{{ device.description }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -392,18 +391,6 @@ function testHamlib() {
|
||||||
data-bs-toggle="collapse"
|
data-bs-toggle="collapse"
|
||||||
>
|
>
|
||||||
Version
|
Version
|
||||||
<span
|
|
||||||
class="badge ms-2"
|
|
||||||
:class="
|
|
||||||
updateAvailable === '1' ? 'bg-warning' : 'bg-success'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
updateAvailable === "1"
|
|
||||||
? "Update available ! ! ! !"
|
|
||||||
: "Current"
|
|
||||||
}}</span
|
|
||||||
>
|
|
||||||
</button>
|
</button>
|
||||||
</h2>
|
</h2>
|
||||||
<div
|
<div
|
||||||
|
@ -426,9 +413,6 @@ function testHamlib() {
|
||||||
>
|
>
|
||||||
Modem version | {{ state.modem_version }}
|
Modem version | {{ state.modem_version }}
|
||||||
</button>
|
</button>
|
||||||
<div :class="updateAvailable === '1' ? '' : 'd-none'">
|
|
||||||
<settings_updater_core />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import settings_updater from "./settings_updater.vue";
|
|
||||||
import settings_station from "./settings_station.vue";
|
import settings_station from "./settings_station.vue";
|
||||||
import settings_gui from "./settings_gui.vue";
|
import settings_gui from "./settings_gui.vue";
|
||||||
import settings_chat from "./settings_chat.vue";
|
import settings_chat from "./settings_chat.vue";
|
||||||
|
@ -23,20 +22,6 @@ import settings_exp from "./settings_exp.vue";
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button
|
<button
|
||||||
class="nav-link active"
|
class="nav-link active"
|
||||||
id="updater-tab"
|
|
||||||
data-bs-toggle="tab"
|
|
||||||
data-bs-target="#updater"
|
|
||||||
type="button"
|
|
||||||
role="tab"
|
|
||||||
aria-controls="home"
|
|
||||||
aria-selected="true"
|
|
||||||
>
|
|
||||||
Updater
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item" role="presentation">
|
|
||||||
<button
|
|
||||||
class="nav-link"
|
|
||||||
id="station-tab"
|
id="station-tab"
|
||||||
data-bs-toggle="tab"
|
data-bs-toggle="tab"
|
||||||
data-bs-target="#station"
|
data-bs-target="#station"
|
||||||
|
@ -141,23 +126,10 @@ import settings_exp from "./settings_exp.vue";
|
||||||
>
|
>
|
||||||
<!-- SETTINGS Nav Tab panes -->
|
<!-- SETTINGS Nav Tab panes -->
|
||||||
|
|
||||||
<!-- Updater tab contents-->
|
|
||||||
<div class="tab-content">
|
|
||||||
<div
|
|
||||||
class="tab-pane active"
|
|
||||||
id="updater"
|
|
||||||
role="tabpanel"
|
|
||||||
aria-labelledby="updater-tab"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<settings_updater />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Station tab contents-->
|
<!-- Station tab contents-->
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div
|
<div
|
||||||
class="tab-pane"
|
class="tab-pane active"
|
||||||
id="station"
|
id="station"
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
aria-labelledby="station-tab"
|
aria-labelledby="station-tab"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { settingsStore as settings, onChange } from "../store/settingsStore.js";
|
import { settingsStore as settings, onChange } from "../store/settingsStore.js";
|
||||||
import { serialDeviceOptions } from "../js/deviceFormHelper";
|
import { useSerialStore } from "../store/serialStore";
|
||||||
|
const serialStore = useSerialStore();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -21,13 +22,13 @@ import { serialDeviceOptions } from "../js/deviceFormHelper";
|
||||||
<div class="input-group input-group-sm mb-1">
|
<div class="input-group input-group-sm mb-1">
|
||||||
<span class="input-group-text" style="width: 180px">Rigctld port</span>
|
<span class="input-group-text" style="width: 180px">Rigctld port</span>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="number"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
placeholder="rigctld port"
|
placeholder="rigctld port"
|
||||||
id="hamlib_rigctld_port"
|
id="hamlib_rigctld_port"
|
||||||
aria-label="Device Port"
|
aria-label="Device Port"
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
v-model="settings.remote.RIGCTLD.port"
|
v-model.number="settings.remote.RIGCTLD.port"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -334,18 +335,16 @@ import { serialDeviceOptions } from "../js/deviceFormHelper";
|
||||||
<span class="input-group-text" style="width: 180px">Radio port</span>
|
<span class="input-group-text" style="width: 180px">Radio port</span>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
class="form-select form-select-sm"
|
|
||||||
aria-label=".form-select-sm"
|
|
||||||
id="hamlib_deviceport"
|
|
||||||
style="width: 7rem"
|
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
v-model="settings.remote.RADIO.serial_port"
|
v-model="settings.remote.RADIO.serial_port"
|
||||||
|
class="form-select form-select-sm"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
v-for="option in serialDeviceOptions()"
|
v-for="device in serialStore.serialDevices"
|
||||||
v-bind:value="option.port"
|
:value="device.port"
|
||||||
|
:key="device.port"
|
||||||
>
|
>
|
||||||
{{ option.description }}
|
{{ device.description }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -422,18 +421,18 @@ import { serialDeviceOptions } from "../js/deviceFormHelper";
|
||||||
|
|
||||||
<div class="input-group input-group-sm mb-1">
|
<div class="input-group input-group-sm mb-1">
|
||||||
<span class="input-group-text" style="width: 180px">PTT device port</span>
|
<span class="input-group-text" style="width: 180px">PTT device port</span>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
class="form-select form-select-sm"
|
|
||||||
aria-label=".form-select-sm"
|
|
||||||
id="hamlib_ptt_port"
|
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
v-model="settings.remote.RADIO.ptt_port"
|
v-model="settings.remote.RADIO.ptt_port"
|
||||||
|
class="form-select form-select-sm"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
v-for="option in serialDeviceOptions()"
|
v-for="device in serialStore.serialDevices"
|
||||||
v-bind:value="option.port"
|
:value="device.port"
|
||||||
|
:key="device.port"
|
||||||
>
|
>
|
||||||
{{ option.description }}
|
{{ device.description }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,9 @@ import { useStateStore } from "../store/stateStore.js";
|
||||||
const state = useStateStore(pinia);
|
const state = useStateStore(pinia);
|
||||||
|
|
||||||
import { startModem, stopModem } from "../js/api.js";
|
import { startModem, stopModem } from "../js/api.js";
|
||||||
import { audioInputOptions, audioOutputOptions } from "../js/deviceFormHelper";
|
|
||||||
|
import { useAudioStore } from "../store/audioStore";
|
||||||
|
const audioStore = useAudioStore();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -74,8 +76,8 @@ import { audioInputOptions, audioOutputOptions } from "../js/deviceFormHelper";
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
v-model="settings.remote.AUDIO.input_device"
|
v-model="settings.remote.AUDIO.input_device"
|
||||||
>
|
>
|
||||||
<option v-for="option in audioInputOptions()" v-bind:value="option.id">
|
<option v-for="device in audioStore.audioInputs" :value="device.id">
|
||||||
{{ option.name }} [{{ option.api }}]
|
{{ device.name }} [{{ device.api }}]
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -89,11 +91,12 @@ import { audioInputOptions, audioOutputOptions } from "../js/deviceFormHelper";
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
v-model="settings.remote.AUDIO.output_device"
|
v-model="settings.remote.AUDIO.output_device"
|
||||||
>
|
>
|
||||||
<option v-for="option in audioOutputOptions()" v-bind:value="option.id">
|
<option v-for="device in audioStore.audioOutputs" :value="device.id">
|
||||||
{{ option.name }} [{{ option.api }}]
|
{{ device.name }} [{{ device.api }}]
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Audio rx level-->
|
<!-- Audio rx level-->
|
||||||
<div class="input-group input-group-sm mb-1">
|
<div class="input-group input-group-sm mb-1">
|
||||||
<span class="input-group-text w-25">RX Audio Level</span>
|
<span class="input-group-text w-25">RX Audio Level</span>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { settingsStore as settings, onChange } from "../store/settingsStore.js";
|
import { settingsStore as settings, onChange } from "../store/settingsStore.js";
|
||||||
import { serialDeviceOptions } from "../js/deviceFormHelper";
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import settings_updater_core from "./settings_updater_core.vue";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div class="alert alert-warning" role="alert">
|
|
||||||
The updater might not working, yet! Please update manually if you are running into problems!
|
|
||||||
</div>
|
|
||||||
<div class="alert alert-warning" role="alert">
|
|
||||||
The updater doesnt contain the server related parts, yet! We are discussing this topic actually, feel free contributing with your opinion on Discord!
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<settings_updater_core />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,102 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { setActivePinia } from "pinia";
|
|
||||||
import pinia from "../store/index";
|
|
||||||
setActivePinia(pinia);
|
|
||||||
|
|
||||||
import { useStateStore } from "../store/stateStore.js";
|
|
||||||
import { settingsStore } from "../store/settingsStore";
|
|
||||||
import { onMounted } from "vue";
|
|
||||||
import { ipcRenderer } from "electron";
|
|
||||||
const state = useStateStore(pinia);
|
|
||||||
onMounted(() => {
|
|
||||||
window.addEventListener("DOMContentLoaded", () => {
|
|
||||||
// we are using this area for implementing the electron runUpdater
|
|
||||||
// we need access to DOM for displaying updater results in GUI
|
|
||||||
// close app, update and restart
|
|
||||||
document
|
|
||||||
.getElementById("update_and_install")
|
|
||||||
.addEventListener("click", () => {
|
|
||||||
ipcRenderer.send("request-restart-and-install-update");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="card m-2">
|
|
||||||
<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>
|
|
||||||
</div>
|
|
||||||
<div class="col-3">
|
|
||||||
<strong class="fs-5">Updater</strong>
|
|
||||||
</div>
|
|
||||||
<div class="col-7">
|
|
||||||
<div class="progress w-100 ms-1 m-1">
|
|
||||||
<div
|
|
||||||
class="progress-bar"
|
|
||||||
style="width: 0%"
|
|
||||||
role="progressbar"
|
|
||||||
id="UpdateProgressBar"
|
|
||||||
aria-valuenow="0"
|
|
||||||
aria-valuemin="0"
|
|
||||||
aria-valuemax="100"
|
|
||||||
>
|
|
||||||
<span id="UpdateProgressInfo"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-1 text-end">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
id="openHelpModalUpdater"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
data-bs-target="#updaterHelpModal"
|
|
||||||
class="btn m-0 p-0 border-0"
|
|
||||||
>
|
|
||||||
<i class="bi bi-question-circle" style="font-size: 1rem"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-body p-2 mb-1">
|
|
||||||
<button
|
|
||||||
class="btn btn-secondary btn-sm ms-1 me-1"
|
|
||||||
id="updater_channel"
|
|
||||||
type="button"
|
|
||||||
disabled
|
|
||||||
>
|
|
||||||
Update channel: {{ settingsStore.local.update_channel }}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="btn btn-secondary btn-sm ms-1"
|
|
||||||
id="updater_status"
|
|
||||||
type="button"
|
|
||||||
disabled
|
|
||||||
>
|
|
||||||
...
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="btn btn-secondary btn-sm ms-1"
|
|
||||||
id="updater_changelog"
|
|
||||||
type="button"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
data-bs-target="#updaterReleaseNotes"
|
|
||||||
>
|
|
||||||
Changelog
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="btn btn-primary btn-sm ms-1"
|
|
||||||
id="update_and_install"
|
|
||||||
type="button"
|
|
||||||
style="display: none"
|
|
||||||
>
|
|
||||||
Install & Restart
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,53 +0,0 @@
|
||||||
import { getAudioDevices, getSerialDevices } from "./api";
|
|
||||||
|
|
||||||
let audioDevices = await getAudioDevices();
|
|
||||||
let serialDevices = await getSerialDevices();
|
|
||||||
|
|
||||||
//Dummy device data sent if unable to get devices from modem to prevent GUI crash
|
|
||||||
const skel = JSON.parse(`
|
|
||||||
[{
|
|
||||||
"api": "MME",
|
|
||||||
"id": "0000",
|
|
||||||
"name": "No devices received from modem",
|
|
||||||
"native_index": 0
|
|
||||||
}]`);
|
|
||||||
|
|
||||||
export function loadAudioDevices() {
|
|
||||||
getAudioDevices().then((devices) => {
|
|
||||||
audioDevices = devices;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function loadSerialDevices() {
|
|
||||||
getSerialDevices().then((devices) => {
|
|
||||||
serialDevices = devices;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function audioInputOptions() {
|
|
||||||
if (audioDevices === undefined) {
|
|
||||||
return skel;
|
|
||||||
}
|
|
||||||
return audioDevices.in;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function audioOutputOptions() {
|
|
||||||
if (audioDevices === undefined) {
|
|
||||||
return skel;
|
|
||||||
}
|
|
||||||
|
|
||||||
return audioDevices.out;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function serialDeviceOptions() {
|
|
||||||
//Return ignore option if no serialDevices
|
|
||||||
if (serialDevices === undefined)
|
|
||||||
return [{ description: "-- ignore --", port: "ignore" }];
|
|
||||||
|
|
||||||
if (serialDevices.findIndex((device) => device.port == "ignore") == -1) {
|
|
||||||
//Add an ignore option for rig and ptt for transceivers that don't require them
|
|
||||||
serialDevices.push({ description: "-- ignore --", port: "ignore" });
|
|
||||||
}
|
|
||||||
|
|
||||||
return serialDevices;
|
|
||||||
}
|
|
|
@ -8,16 +8,15 @@ import {
|
||||||
} from "./chatHandler";
|
} from "./chatHandler";
|
||||||
*/
|
*/
|
||||||
import { displayToast } from "./popupHandler";
|
import { displayToast } from "./popupHandler";
|
||||||
import {
|
import { getFreedataMessages, getModemState, getAudioDevices } from "./api";
|
||||||
getFreedataMessages,
|
|
||||||
getConfig,
|
|
||||||
getAudioDevices,
|
|
||||||
getSerialDevices,
|
|
||||||
getModemState,
|
|
||||||
} from "./api";
|
|
||||||
import { processFreedataMessages } from "./messagesHandler.ts";
|
import { processFreedataMessages } from "./messagesHandler.ts";
|
||||||
import { processRadioStatus } from "./radioHandler.ts";
|
import { processRadioStatus } from "./radioHandler.ts";
|
||||||
|
|
||||||
|
import { useAudioStore } from "../store/audioStore";
|
||||||
|
const audioStore = useAudioStore();
|
||||||
|
import { useSerialStore } from "../store/serialStore";
|
||||||
|
const serialStore = useSerialStore();
|
||||||
|
|
||||||
// ----------------- init pinia stores -------------
|
// ----------------- init pinia stores -------------
|
||||||
import { setActivePinia } from "pinia";
|
import { setActivePinia } from "pinia";
|
||||||
import pinia from "../store/index";
|
import pinia from "../store/index";
|
||||||
|
@ -30,6 +29,17 @@ import {
|
||||||
getRemote,
|
getRemote,
|
||||||
} from "../store/settingsStore.js";
|
} from "../store/settingsStore.js";
|
||||||
|
|
||||||
|
export function loadAllData() {
|
||||||
|
getModemState();
|
||||||
|
getRemote();
|
||||||
|
getOverallHealth();
|
||||||
|
audioStore.loadAudioDevices();
|
||||||
|
serialStore.loadSerialDevices();
|
||||||
|
getFreedataMessages();
|
||||||
|
processFreedataMessages();
|
||||||
|
processRadioStatus();
|
||||||
|
}
|
||||||
|
|
||||||
export function connectionFailed(endpoint, event) {
|
export function connectionFailed(endpoint, event) {
|
||||||
stateStore.modem_connection = "disconnected";
|
stateStore.modem_connection = "disconnected";
|
||||||
}
|
}
|
||||||
|
@ -95,12 +105,7 @@ export function eventDispatcher(data) {
|
||||||
switch (data["modem"]) {
|
switch (data["modem"]) {
|
||||||
case "started":
|
case "started":
|
||||||
displayToast("success", "bi-arrow-left-right", "Modem started", 5000);
|
displayToast("success", "bi-arrow-left-right", "Modem started", 5000);
|
||||||
getModemState();
|
loadAllData();
|
||||||
getConfig();
|
|
||||||
getAudioDevices();
|
|
||||||
getSerialDevices();
|
|
||||||
getFreedataMessages();
|
|
||||||
processRadioStatus();
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case "stopped":
|
case "stopped":
|
||||||
|
@ -109,12 +114,7 @@ export function eventDispatcher(data) {
|
||||||
|
|
||||||
case "restarted":
|
case "restarted":
|
||||||
displayToast("secondary", "bi-bootstrap-reboot", "Modem restarted", 5000);
|
displayToast("secondary", "bi-bootstrap-reboot", "Modem restarted", 5000);
|
||||||
getModemState();
|
loadAllData();
|
||||||
getConfig();
|
|
||||||
getAudioDevices();
|
|
||||||
getSerialDevices();
|
|
||||||
getFreedataMessages();
|
|
||||||
processRadioStatus();
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case "failed":
|
case "failed":
|
||||||
|
@ -135,19 +135,7 @@ export function eventDispatcher(data) {
|
||||||
displayToast("success", "bi-ethernet", message, 5000);
|
displayToast("success", "bi-ethernet", message, 5000);
|
||||||
stateStore.modem_connection = "connected";
|
stateStore.modem_connection = "connected";
|
||||||
|
|
||||||
getRemote().then(() => {
|
loadAllData();
|
||||||
//initConnections();
|
|
||||||
getModemState();
|
|
||||||
});
|
|
||||||
|
|
||||||
//getConfig();
|
|
||||||
getModemState();
|
|
||||||
getOverallHealth();
|
|
||||||
getAudioDevices();
|
|
||||||
getSerialDevices();
|
|
||||||
getFreedataMessages();
|
|
||||||
processFreedataMessages();
|
|
||||||
processRadioStatus();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
39
gui/src/store/audioStore.js
Normal file
39
gui/src/store/audioStore.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { getAudioDevices } from "../js/api";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
// Define skel fallback data
|
||||||
|
const skel = [
|
||||||
|
{
|
||||||
|
api: "ERR",
|
||||||
|
id: "0000",
|
||||||
|
name: "No devices received from modem",
|
||||||
|
native_index: 0,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const useAudioStore = defineStore("audioStore", () => {
|
||||||
|
const audioInputs = ref([]);
|
||||||
|
const audioOutputs = ref([]);
|
||||||
|
|
||||||
|
const loadAudioDevices = async () => {
|
||||||
|
try {
|
||||||
|
const devices = await getAudioDevices();
|
||||||
|
// Check if devices are valid and have entries, otherwise use skel
|
||||||
|
audioInputs.value = devices && devices.in.length > 0 ? devices.in : skel;
|
||||||
|
audioOutputs.value =
|
||||||
|
devices && devices.out.length > 0 ? devices.out : skel;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to load audio devices:", error);
|
||||||
|
// Use skel as fallback in case of error
|
||||||
|
audioInputs.value = skel;
|
||||||
|
audioOutputs.value = skel;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
audioInputs,
|
||||||
|
audioOutputs,
|
||||||
|
loadAudioDevices,
|
||||||
|
};
|
||||||
|
});
|
38
gui/src/store/serialStore.js
Normal file
38
gui/src/store/serialStore.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { getSerialDevices } from "../js/api"; // Make sure this points to the correct file
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
// Define "skel" fallback data for serial devices
|
||||||
|
const skelSerial = [
|
||||||
|
{
|
||||||
|
description: "No devices received from modem",
|
||||||
|
port: "ignore", // Using "ignore" as a placeholder value
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const useSerialStore = defineStore("serialStore", () => {
|
||||||
|
const serialDevices = ref([]);
|
||||||
|
|
||||||
|
const loadSerialDevices = async () => {
|
||||||
|
try {
|
||||||
|
const devices = await getSerialDevices();
|
||||||
|
// Check if devices are valid and have entries, otherwise use skelSerial
|
||||||
|
serialDevices.value =
|
||||||
|
devices && devices.length > 0 ? devices : skelSerial;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to load serial devices:", error);
|
||||||
|
// Use skelSerial as fallback in case of error
|
||||||
|
serialDevices.value = skelSerial;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the "-- ignore --" option is always available
|
||||||
|
if (!serialDevices.value.some((device) => device.port === "ignore")) {
|
||||||
|
serialDevices.value.push({ description: "-- ignore --", port: "ignore" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
serialDevices,
|
||||||
|
loadSerialDevices,
|
||||||
|
};
|
||||||
|
});
|
|
@ -74,23 +74,20 @@ def freedv_get_mode_name_by_value(mode: int) -> str:
|
||||||
return FREEDV_MODE(mode).name
|
return FREEDV_MODE(mode).name
|
||||||
|
|
||||||
|
|
||||||
# Check if we are running in a pyinstaller environment
|
# Get the directory of the current script file
|
||||||
#if hasattr(sys, "_MEIPASS"):
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
# sys.path.append(getattr(sys, "_MEIPASS"))
|
sys.path.append(script_dir)
|
||||||
#else:
|
# Use script_dir to construct the paths for file search
|
||||||
sys.path.append(os.path.abspath("."))
|
|
||||||
|
|
||||||
#log.info("[C2 ] Searching for libcodec2...")
|
|
||||||
if sys.platform == "linux":
|
if sys.platform == "linux":
|
||||||
files = glob.glob(r"**/*libcodec2*", recursive=True)
|
files = glob.glob(os.path.join(script_dir, "**/*libcodec2*"), recursive=True)
|
||||||
files.append("libcodec2.so")
|
files.append(os.path.join(script_dir, "libcodec2.so"))
|
||||||
elif sys.platform == "darwin":
|
elif sys.platform == "darwin":
|
||||||
if hasattr(sys, "_MEIPASS"):
|
if hasattr(sys, "_MEIPASS"):
|
||||||
files = glob.glob(getattr(sys, "_MEIPASS") + '/**/*libcodec2*', recursive=True)
|
files = glob.glob(os.path.join(getattr(sys, "_MEIPASS"), '**/*libcodec2*'), recursive=True)
|
||||||
else:
|
else:
|
||||||
files = glob.glob(r"**/*libcodec2*.dylib", recursive=True)
|
files = glob.glob(os.path.join(script_dir, "**/*libcodec2*.dylib"), recursive=True)
|
||||||
elif sys.platform in ["win32", "win64"]:
|
elif sys.platform in ["win32", "win64"]:
|
||||||
files = glob.glob(r"**\*libcodec2*.dll", recursive=True)
|
files = glob.glob(os.path.join(script_dir, "**\\*libcodec2*.dll"), recursive=True)
|
||||||
else:
|
else:
|
||||||
files = []
|
files = []
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,16 @@ from message_system_db_manager import DatabaseManager
|
||||||
from message_system_db_model import MessageAttachment, Attachment, P2PMessage
|
from message_system_db_model import MessageAttachment, Attachment, P2PMessage
|
||||||
import json
|
import json
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
class DatabaseManagerAttachments(DatabaseManager):
|
class DatabaseManagerAttachments(DatabaseManager):
|
||||||
def __init__(self, uri='sqlite:///freedata-messages.db'):
|
def __init__(self, db_file=None):
|
||||||
super().__init__(uri)
|
if not db_file:
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
db_path = os.path.join(script_dir, 'freedata-messages.db')
|
||||||
|
db_file = 'sqlite:///' + db_path
|
||||||
|
super().__init__(db_file)
|
||||||
|
|
||||||
|
|
||||||
def add_attachment(self, session, message, attachment_data):
|
def add_attachment(self, session, message, attachment_data):
|
||||||
|
|
|
@ -4,14 +4,16 @@ from sqlalchemy.orm import scoped_session, sessionmaker
|
||||||
from threading import local
|
from threading import local
|
||||||
from message_system_db_model import Base, Beacon, Station, Status, Attachment, P2PMessage
|
from message_system_db_model import Base, Beacon, Station, Status, Attachment, P2PMessage
|
||||||
from datetime import timezone, timedelta, datetime
|
from datetime import timezone, timedelta, datetime
|
||||||
import json
|
import os
|
||||||
import structlog
|
|
||||||
import helpers
|
|
||||||
|
|
||||||
|
|
||||||
class DatabaseManagerBeacon(DatabaseManager):
|
class DatabaseManagerBeacon(DatabaseManager):
|
||||||
def __init__(self, uri):
|
def __init__(self, db_file=None):
|
||||||
super().__init__(uri)
|
if not db_file:
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
db_path = os.path.join(script_dir, 'freedata-messages.db')
|
||||||
|
db_file = 'sqlite:///' + db_path
|
||||||
|
|
||||||
|
super().__init__(db_file)
|
||||||
|
|
||||||
def add_beacon(self, timestamp, callsign, snr, gridsquare):
|
def add_beacon(self, timestamp, callsign, snr, gridsquare):
|
||||||
session = None
|
session = None
|
||||||
|
|
|
@ -7,12 +7,17 @@ from threading import local
|
||||||
from message_system_db_model import Base, Station, Status
|
from message_system_db_model import Base, Station, Status
|
||||||
import structlog
|
import structlog
|
||||||
import helpers
|
import helpers
|
||||||
|
import os
|
||||||
|
|
||||||
class DatabaseManager:
|
class DatabaseManager:
|
||||||
def __init__(self, event_manger, uri='sqlite:///freedata-messages.db'):
|
def __init__(self, event_manger, db_file=None):
|
||||||
self.event_manager = event_manger
|
self.event_manager = event_manger
|
||||||
|
if not db_file:
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
db_path = os.path.join(script_dir, 'freedata-messages.db')
|
||||||
|
db_file = 'sqlite:///' + db_path
|
||||||
|
|
||||||
self.engine = create_engine(uri, echo=False)
|
self.engine = create_engine(db_file, echo=False)
|
||||||
self.thread_local = local()
|
self.thread_local = local()
|
||||||
self.session_factory = sessionmaker(bind=self.engine)
|
self.session_factory = sessionmaker(bind=self.engine)
|
||||||
Base.metadata.create_all(self.engine)
|
Base.metadata.create_all(self.engine)
|
||||||
|
|
|
@ -4,12 +4,18 @@ from message_system_db_model import Status, P2PMessage
|
||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
class DatabaseManagerMessages(DatabaseManager):
|
class DatabaseManagerMessages(DatabaseManager):
|
||||||
def __init__(self, uri='sqlite:///freedata-messages.db'):
|
def __init__(self, db_file=None):
|
||||||
super().__init__(uri)
|
if not db_file:
|
||||||
self.attachments_manager = DatabaseManagerAttachments(uri)
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
db_path = os.path.join(script_dir, 'freedata-messages.db')
|
||||||
|
db_file = 'sqlite:///' + db_path
|
||||||
|
|
||||||
|
super().__init__(db_file)
|
||||||
|
self.attachments_manager = DatabaseManagerAttachments(db_file)
|
||||||
|
|
||||||
def add_message(self, message_data, statistics, direction='receive', status=None, is_read=True):
|
def add_message(self, message_data, statistics, direction='receive', status=None, is_read=True):
|
||||||
session = self.get_thread_scoped_session()
|
session = self.get_thread_scoped_session()
|
||||||
|
|
|
@ -36,7 +36,8 @@ def set_config():
|
||||||
if 'FREEDATA_CONFIG' in os.environ:
|
if 'FREEDATA_CONFIG' in os.environ:
|
||||||
config_file = os.environ['FREEDATA_CONFIG']
|
config_file = os.environ['FREEDATA_CONFIG']
|
||||||
else:
|
else:
|
||||||
config_file = 'config.ini'
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
config_file = os.path.join(script_dir, 'config.ini')
|
||||||
|
|
||||||
if os.path.exists(config_file):
|
if os.path.exists(config_file):
|
||||||
print(f"Using config from {config_file}")
|
print(f"Using config from {config_file}")
|
||||||
|
|
Loading…
Reference in a new issue