mirror of https://github.com/DJ2LS/FreeDATA.git
Merge branch 'develop' into dev-connected-mode
commit
7a885d65e5
|
@ -153,6 +153,36 @@ export function eventDispatcher(data) {
|
|||
loadAllData();
|
||||
return;
|
||||
|
||||
case "message-logging":
|
||||
if (data.endpoint === "wavelog" || data.endpoint === "udp") {
|
||||
if (data.status === true) {
|
||||
const message = `
|
||||
<div>
|
||||
<strong>${i18next.t('popups.adiflogheader')}:</strong>
|
||||
<span class="badge bg-success">${i18next.t('popups.adiflogtext1')}${data.message}${i18next.t('popups.adiflogtext2')}</span>
|
||||
<div class="mt-2">
|
||||
<span class="badge bg-secondary">${data.endpoint} ${i18next.t('popups.adiflogheader')}</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
displayToast("success", "bi-check-circle", message, 5000);
|
||||
} else {
|
||||
const message = `
|
||||
<div>
|
||||
<strong>${i18next.t('popups.adiflogheader')}:</strong>
|
||||
<span class="badge bg-danger">${data.message}</span>
|
||||
<div class="mt-2">
|
||||
<span class="badge bg-secondary">${data.endpoint} ${i18next.t('popups.adiflogerror')}</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
displayToast("warning", "bi-exclamation-circle", message, 5000);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
|
||||
|
||||
case "frame-handler":
|
||||
switch (data.received) {
|
||||
case "CQ":
|
||||
|
|
|
@ -33,7 +33,11 @@
|
|||
"bytesperminute": "Bytes per minute",
|
||||
"transmissionfailedwith": "Transmission FAILED with",
|
||||
"confirmingtransmissionwith": "Confirming transmission with",
|
||||
"receivedbytes": "Received Bytes"
|
||||
"receivedbytes": "Received Bytes",
|
||||
"adiflogheader": "ADIF",
|
||||
"adiflogtext1": "QSO with",
|
||||
"adiflogtext2": "added to the log.",
|
||||
"adiflogerror": "ADIF export error"
|
||||
},
|
||||
"navbar": {
|
||||
"frequency_help": "What's the frequency, Kenneth?",
|
||||
|
|
|
@ -33,7 +33,11 @@
|
|||
"bytesperminute": "Byte per minutt",
|
||||
"transmissionfailedwith": "Overføring MISLYKKET med",
|
||||
"confirmingtransmissionwith": "Bekrefter overføring med",
|
||||
"receivedbytes": "Mottatte bytes"
|
||||
"receivedbytes": "Mottatte bytes",
|
||||
"adiflogheader": "ADIF",
|
||||
"adiflogtext1": "QSO med",
|
||||
"adiflogtext2": "lagt til i loggen.",
|
||||
"adiflogerror": "ADIF export feilet"
|
||||
},
|
||||
"navbar": {
|
||||
"frequency_help": "Hva er frekvensen, Kenneth?",
|
||||
|
|
|
@ -1,42 +1,50 @@
|
|||
"""
|
||||
This module provides a utility function to send ADIF-formatted QSO data over UDP.
|
||||
It reads configuration settings from a provided dictionary to determine if ADIF UDP logging is enabled,
|
||||
and if so, retrieves the destination host and port. Using a UDP socket, it encodes the ADIF data as UTF-8 and
|
||||
sends it to the specified server.
|
||||
"""
|
||||
|
||||
|
||||
import socket
|
||||
import structlog
|
||||
import threading
|
||||
|
||||
def send_adif_qso_data(config, adif_data):
|
||||
def send_adif_qso_data(config, event_manager, adif_data):
|
||||
"""
|
||||
Sends ADIF QSO data to the specified server via UDP.
|
||||
Sends ADIF QSO data to the specified server via UDP in a non-blocking manner.
|
||||
|
||||
Parameters:
|
||||
server_ip (str): IP address of the server.
|
||||
server_port (int): Port of the server.
|
||||
config (dict): Configuration settings.
|
||||
event_manager: An event manager to log success/failure.
|
||||
adif_data (str): ADIF-formatted QSO data.
|
||||
"""
|
||||
|
||||
log = structlog.get_logger()
|
||||
|
||||
# If False then exit the function
|
||||
# Check if ADIF UDP logging is enabled
|
||||
adif = config['QSO_LOGGING'].get('enable_adif_udp', 'False')
|
||||
|
||||
if not adif:
|
||||
return # exit as we don't want to log ADIF UDP
|
||||
return # Exit if ADIF UDP logging is disabled
|
||||
|
||||
adif_log_host = config['QSO_LOGGING'].get('adif_udp_host', '127.0.0.1')
|
||||
adif_log_port = int(config['QSO_LOGGING'].get('adif_udp_port', '2237'))
|
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
try:
|
||||
def send_thread():
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
# Set a timeout of 3 seconds to avoid blocking indefinitely
|
||||
sock.settimeout(3)
|
||||
|
||||
# Send the ADIF data to the server
|
||||
sock.sendto(adif_data.encode('utf-8'), (adif_log_host, adif_log_port))
|
||||
log.info(f"[CHAT] ADIF QSO data sent to: {adif_log_host}:{adif_log_port} {adif_data.encode('utf-8')}")
|
||||
except Exception as e:
|
||||
log.info(f"[CHAT] Error sending ADIF data: {e}")
|
||||
finally:
|
||||
sock.close()
|
||||
callsign_start = adif_data.find(f">") + 1
|
||||
callsign_end = adif_data.find(f"<QSO_DATE", callsign_start)
|
||||
call_value = adif_data[callsign_start:callsign_end]
|
||||
|
||||
try:
|
||||
sock.sendto(adif_data.encode('utf-8'), (adif_log_host, adif_log_port))
|
||||
log.info(f"[CHAT] ADIF QSO data sent to: {adif_log_host}:{adif_log_port}")
|
||||
event_manager.freedata_logging(type="udp", status=True, message=f" {call_value} ")
|
||||
|
||||
except socket.timeout:
|
||||
log.info(f"[CHAT] Timeout occurred sending ADIF data to {adif_log_host}:{adif_log_port}")
|
||||
event_manager.freedata_logging(type="udp", status=True, message=f" {call_value} ")
|
||||
except Exception as e:
|
||||
log.info(f"[CHAT] Error sending ADIF data: {e}")
|
||||
event_manager.freedata_logging(type="udp", status=True, message=f" {call_value} ")
|
||||
|
||||
finally:
|
||||
sock.close()
|
||||
|
||||
# Run the sending function in a separate thread
|
||||
thread = threading.Thread(target=send_thread, daemon=True)
|
||||
thread.start()
|
||||
|
|
|
@ -85,9 +85,9 @@ async def post_freedata_message_adif_log(message_id: str, request:Request):
|
|||
if not adif_output:
|
||||
return
|
||||
|
||||
# Send the ADIF data via UDP
|
||||
adif_udp_logger.send_adif_qso_data(request.app.config_manager.read(), adif_output)
|
||||
wavelog_api_logger.send_wavelog_qso_data(request.app.config_manager.read(), adif_output)
|
||||
# Send the ADIF data via UDP and/or wavelog
|
||||
adif_udp_logger.send_adif_qso_data(request.app.config_manager.read(), request.app.event_manager, adif_output)
|
||||
wavelog_api_logger.send_wavelog_qso_data(request.app.config_manager.read(), request.app.event_manager, adif_output)
|
||||
return api_response(adif_output)
|
||||
|
||||
@router.patch("/messages/{message_id}", summary="Update Message by ID", tags=["FreeDATA"], responses={
|
||||
|
|
|
@ -238,4 +238,20 @@ class EventManager:
|
|||
Args:
|
||||
message_id (any, optional): The ID of the changed message. Defaults to None.
|
||||
"""
|
||||
self.broadcast({"message-db": "changed", "message_id": message_id})
|
||||
self.broadcast({"message-db": "changed", "message_id": message_id})
|
||||
|
||||
def freedata_logging(self, type, status, message):
|
||||
"""Broadcasts a FreeDATA logging event.
|
||||
|
||||
This method broadcasts an event related to FreeDATA logging,
|
||||
indicating the type of logging endpoint and its status. It is
|
||||
used to inform other parts of the application about logging
|
||||
activities.
|
||||
|
||||
Args:
|
||||
type (str): The type of logging endpoint (e.g., "file", "websocket").
|
||||
status (any): The status of the logging operation.
|
||||
message (str): The message to be displayed
|
||||
"""
|
||||
|
||||
self.broadcast({"type": "message-logging", "endpoint": type, "status": status, "message": message})
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import requests
|
||||
import re
|
||||
import threading
|
||||
import structlog
|
||||
|
||||
def send_wavelog_qso_data(config, wavelog_data):
|
||||
|
||||
def send_wavelog_qso_data(config, event_manager, wavelog_data):
|
||||
"""
|
||||
Sends wavelog QSO data to the specified server via API call.
|
||||
|
||||
|
@ -41,9 +42,21 @@ def send_wavelog_qso_data(config, wavelog_data):
|
|||
"string": wavelog_data
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(url, headers=headers, json=data)
|
||||
response.raise_for_status() # Raise an error for bad status codes
|
||||
log.info(f"[CHAT] Wavelog API: {wavelog_data}")
|
||||
except requests.exceptions.RequestException as e:
|
||||
log.warning(f"[WAVELOG ADIF API EXCEPTION]: {e}")
|
||||
def send_api():
|
||||
try:
|
||||
response = requests.post(url, headers=headers, json=data)
|
||||
response.raise_for_status() # Raise an error for bad status codes
|
||||
log.info(f"[CHAT] Wavelog API: {wavelog_data}")
|
||||
|
||||
callsign_start = wavelog_data.find(f">") + 1
|
||||
callsign_end = wavelog_data.find(f"<QSO_DATE", callsign_start)
|
||||
call_value = wavelog_data[callsign_start:callsign_end]
|
||||
|
||||
event_manager.freedata_logging(type="wavelog", status=True, message=f" {call_value} ")
|
||||
|
||||
except Exception as e:
|
||||
event_manager.freedata_logging(type="wavelog", status=False, message=f"{e}")
|
||||
|
||||
# Run the API call in a background thread to avoid blocking the main thread
|
||||
thread = threading.Thread(target=send_api, daemon=True)
|
||||
thread.start()
|
Loading…
Reference in New Issue