kopia lustrzana https://github.com/jamescoxon/dl-fldigi
442 wiersze
11 KiB
C++
442 wiersze
11 KiB
C++
// =====================================================================
|
|
//
|
|
// maclogger.cxx
|
|
//
|
|
// receive log data from maclogger udp broadcast message
|
|
//
|
|
// Copyright (C) 2016
|
|
// Dave Freese, W1HKJ
|
|
//
|
|
// This file is part of fldigi.
|
|
//
|
|
// Fldigi is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Fldigi is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
|
|
// =====================================================================
|
|
|
|
#include <iostream>
|
|
#include <cmath>
|
|
#include <cstring>
|
|
#include <vector>
|
|
#include <list>
|
|
#include <stdlib.h>
|
|
|
|
#include <FL/Fl_Text_Display.H>
|
|
#include <FL/Fl_Text_Buffer.H>
|
|
|
|
#include "rigsupport.h"
|
|
#include "modem.h"
|
|
#include "trx.h"
|
|
#include "fl_digi.h"
|
|
#include "configuration.h"
|
|
#include "main.h"
|
|
#include "waterfall.h"
|
|
#include "macros.h"
|
|
#include "qrunner.h"
|
|
#include "debug.h"
|
|
#include "status.h"
|
|
#include "icons.h"
|
|
|
|
#include "maclogger.h"
|
|
|
|
#include "confdialog.h"
|
|
|
|
LOG_FILE_SOURCE(debug::LOG_MACLOGGER);
|
|
|
|
using namespace std;
|
|
|
|
//======================================================================
|
|
// Socket MACLOGGER i/o used on all platforms
|
|
//======================================================================
|
|
|
|
pthread_t maclogger_thread;
|
|
pthread_t maclogger_rx_socket_thread;
|
|
pthread_mutex_t mclg_str_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
Socket *maclogger_socket = 0;
|
|
|
|
bool maclogger_enabled = false;
|
|
bool maclogger_exit = false;
|
|
|
|
string maclogger_ip_address= "";;
|
|
string maclogger_ip_port= "";;
|
|
|
|
string mclg_str = "";
|
|
int mclg_rxhz;
|
|
int mclg_txhz;
|
|
string mclg_band;
|
|
string mclg_mode;
|
|
string mclg_power;
|
|
string mclg_call;
|
|
string mclg_dxccnum;
|
|
string mclg_dxccstr;
|
|
string mclg_city;
|
|
string mclg_state;
|
|
string mclg_firstname;
|
|
string mclg_lastname;
|
|
string mclg_comment;
|
|
string mclg_bearing;
|
|
string mclg_longpath;
|
|
string mclg_distance;
|
|
|
|
//======================================================================
|
|
// MacLogger UDP string parsing
|
|
//======================================================================
|
|
|
|
static string get_str(string s)
|
|
{
|
|
size_t p = s.find(":");
|
|
if (p == string::npos) return "";
|
|
s.erase(0, p+1);
|
|
p = s.find(",");
|
|
if (p == string::npos) p = s.find("]");
|
|
if (p == string::npos) return "";
|
|
string s2 = s.substr(0, p);
|
|
if (s2 == "(null)") return "";
|
|
return s2;
|
|
}
|
|
|
|
static int get_freq(string s)
|
|
{
|
|
string s2 = get_str(s);
|
|
float mhz;
|
|
sscanf(s2.c_str(), "%f", &mhz);
|
|
int hz = mhz * 1e6;
|
|
return hz;
|
|
}
|
|
|
|
void maclogger_set_qsy()
|
|
{
|
|
int hz = mclg_txhz;
|
|
if (hz <= 0) hz = mclg_rxhz;
|
|
if (hz <= 0) return;
|
|
wf->rfcarrier(hz);
|
|
wf->movetocenter();
|
|
show_frequency(hz);
|
|
}
|
|
|
|
void maclogger_set_call()
|
|
{
|
|
inpCall->value(mclg_call.c_str());
|
|
inpCall->do_callback();
|
|
}
|
|
|
|
void maclogger_set_name()
|
|
{
|
|
inpName->value(mclg_firstname.c_str());
|
|
inpName->do_callback();
|
|
}
|
|
|
|
void maclogger_set_mode()
|
|
{
|
|
// inpMode->value(mclg_mode.c_str());
|
|
// inpMode->do_callback();
|
|
}
|
|
|
|
void maclogger_set_qth()
|
|
{
|
|
inpQth->value(mclg_city.c_str());
|
|
inpQth->do_callback();
|
|
}
|
|
|
|
void maclogger_set_state()
|
|
{
|
|
inpState->value(mclg_state.c_str());
|
|
inpState->do_callback();
|
|
}
|
|
|
|
void maclogger_disp_report(const char * s)
|
|
{
|
|
txt_UDP_data->insert(s);
|
|
txt_UDP_data->redraw();
|
|
}
|
|
|
|
void show_mac_strings()
|
|
{
|
|
SET_THREAD_ID(MACLOGGER_TID);
|
|
|
|
if (mclg_txhz > 0) REQ(maclogger_set_qsy);
|
|
else if (mclg_rxhz > 0) REQ(maclogger_set_qsy);
|
|
if (!mclg_mode.empty()) REQ(maclogger_set_mode);
|
|
if (!mclg_call.empty()) REQ(maclogger_set_call);
|
|
if (!mclg_city.empty()) REQ(maclogger_set_qth);
|
|
if (!mclg_state.empty()) REQ(maclogger_set_state);
|
|
if (!mclg_firstname.empty()) REQ(maclogger_set_name);
|
|
|
|
// if (!mclg_power.empty())
|
|
// if (!mclg_band.empty())
|
|
// if (!mclg_lastname.empty())
|
|
// if (!mclg_comment.empty())
|
|
// if (!mclg_bearing.empty())
|
|
// if (!mclg_longpath.empty())
|
|
// if (!mclg_distance.empty())
|
|
// if (!mclg_dxccnum.empty())
|
|
// if (!mclg_dxccstr.empty())
|
|
|
|
}
|
|
|
|
void parse_report(string str)
|
|
{
|
|
size_t p;
|
|
mclg_rxhz = 0;
|
|
mclg_txhz = 0;
|
|
mclg_band.clear();
|
|
mclg_mode.clear();
|
|
mclg_power.clear();
|
|
mclg_call.clear();
|
|
mclg_dxccnum.clear();
|
|
mclg_dxccstr.clear();
|
|
mclg_city.clear();
|
|
mclg_state.clear();
|
|
mclg_firstname.clear();
|
|
mclg_lastname.clear();
|
|
mclg_comment.clear();
|
|
mclg_bearing.clear();
|
|
mclg_longpath.clear();
|
|
mclg_distance.clear();
|
|
|
|
if ((p = str.find("RxMHz:")) != string::npos)
|
|
mclg_rxhz = get_freq(str.substr(p));
|
|
if ((p = str.find("TxMHz:")) != string::npos)
|
|
mclg_txhz = get_freq(str.substr(p));
|
|
if ((p = str.find("Mode:")) != string::npos)
|
|
mclg_mode = get_str(str.substr(p));
|
|
if ((p = str.find("Call:")) != string::npos)
|
|
mclg_call = get_str(str.substr(p));
|
|
if ((p = str.find("city:")) != string::npos)
|
|
mclg_city = get_str(str.substr(p));
|
|
if ((p = str.find("state:")) != string::npos)
|
|
mclg_state = get_str(str.substr(p));
|
|
if ((p = str.find("first_name:")) != string::npos)
|
|
mclg_firstname = get_str(str.substr(p));
|
|
|
|
// if ((p = mclg_str.find("dxcc_num:")) != string::npos)
|
|
// mclg_dxccnum = get_str(mclg_str.substr(p));
|
|
// if ((p = mclg_str.find("dxcc_string:")) != string::npos)
|
|
// mclg_dxccstr = get_str(mclg_str.substr(p));
|
|
// if ((p = mclg_str.find("Power:")) != string::npos)
|
|
// mclg_power = get_str(mclg_str.substr(p));
|
|
// if ((p = mclg_str.find("Band:")) != string::npos)
|
|
// mclg_band = get_str(mclg_str.substr(p));
|
|
// if ((p = mclg_str.find("last_name:")) != string::npos)
|
|
// mclg_lastname = get_str(mclg_str.substr(p));
|
|
// if ((p = mclg_str.find("Comment:")) != string::npos)
|
|
// mclg_comment = get_str(mclg_str.substr(p));
|
|
// if ((p = mclg_str.find("Bearing:")) != string::npos)
|
|
// mclg_bearing = get_str(mclg_str.substr(p));
|
|
// if ((p = mclg_str.find("LongPath:")) != string::npos)
|
|
// mclg_longpath = get_str(mclg_str.substr(p));
|
|
// if ((p = mclg_str.find("Distance:")) != string::npos)
|
|
// mclg_distance = get_str(mclg_str.substr(p));
|
|
|
|
show_mac_strings();
|
|
}
|
|
|
|
void parse_maclog()
|
|
{
|
|
size_t p1, p2;
|
|
string str, srep;
|
|
static string sreport[20];
|
|
int repnbr = 0;
|
|
while (!mclg_str.empty()) {
|
|
p1 = mclg_str.find("[");
|
|
if (p1 == string::npos) return;
|
|
if (p1 != 0) mclg_str.erase(0, p1);
|
|
p2 = mclg_str.find("]");
|
|
if (p2 == string::npos) return;
|
|
|
|
str = mclg_str.substr(0, p2 + 1);
|
|
srep = str;
|
|
srep.append("\n");
|
|
if (repnbr < 20) {
|
|
sreport[repnbr] = srep;
|
|
REQ(maclogger_disp_report, sreport[repnbr].c_str());
|
|
repnbr++;
|
|
}
|
|
|
|
if (progdefaults.enable_maclogger_log) {
|
|
std::string pathname = TempDir;
|
|
pathname.append("maclogger_udp_strings.txt");
|
|
FILE *maclog = fopen(pathname.c_str(), "a");
|
|
fprintf(maclog, "%s", srep.c_str());
|
|
fclose(maclog);
|
|
}
|
|
|
|
if (progdefaults.capture_maclogger_radio &&
|
|
(mclg_str.find("[Radio Report:") == 0)) parse_report(str);
|
|
|
|
else if (progdefaults.capture_maclogger_spot_tune &&
|
|
(mclg_str.find("[SpotTune:") == 0)) parse_report(str);
|
|
|
|
else if (progdefaults.capture_maclogger_spot_report &&
|
|
(mclg_str.find("[Spot Report:") == 0)) parse_report(str);
|
|
|
|
else if (progdefaults.capture_maclogger_log &&
|
|
(mclg_str.find("[Log Report:") == 0)) parse_report(str);
|
|
|
|
else if (progdefaults.capture_maclogger_lookup &&
|
|
(mclg_str.find("[Lookup Report") == 0)) parse_report(str);
|
|
|
|
mclg_str.erase(0, p2 + 1);
|
|
|
|
}
|
|
}
|
|
|
|
//======================================================================
|
|
// uncomment to use UDP test strings
|
|
//
|
|
// #define TESTSTRINGS 1
|
|
//
|
|
//======================================================================
|
|
|
|
#ifdef TESTSTRINGS
|
|
string tstring[6] = {
|
|
"[Radio Report:RxMHz:24.96400, TxMHz:24.96400, Band:12M, Mode:USB, Power:5]",
|
|
"[SpotTune:RxMHz:28.49500, TxMHz:28.49600, Band:10M, Mode:USB]",
|
|
"[Log Report: Call:N2BJ, RxMHz:21.08580, TxMHz:21.08580, Band:15M, Mode:FSK, Power:5, dxcc_num:291, dxcc_string:United States, city:NEW LENOX, state:IL, first_name:Barry, last_name:COHEN]",
|
|
"[Spot Report: RxMHz:3.50300, TxMHz:3.50300, Band:80M, Mode:CW, Call:EP6T, dxcc_string:Iran, Comment:UP , TNX CARLO , GL]",
|
|
"[Rotor Report: Bearing:304.7, LongPath:0, Distance:0.0]",
|
|
"[Lookup Report:Call:YC8RBI, RxMHz:21.32500, Band:15M, Mode:USB, dxcc_num:327, dxcc_string:Indonesia, Bearing:328.1, city:SANGIHE ISLAND NORTH SULAWESI, state:(null), first_name:RICHARD, last_name:BYL ( ICHA )]"
|
|
};
|
|
int tnbr = 0;
|
|
#endif
|
|
|
|
void get_maclogger_udp()
|
|
{
|
|
if(!maclogger_socket) return;
|
|
if (!progdefaults.connect_to_maclogger) return;
|
|
|
|
#ifdef TESTSTRINGS
|
|
if (tnbr == 0) {
|
|
mclg_str = "bogus start chars dkoe13.chfff ";
|
|
for (int n = 0; n < 6; n++) mclg_str.append(tstring[n]);
|
|
mclg_str.append(" and garbage at the end");
|
|
parse_maclog();
|
|
tnbr = 1;
|
|
}
|
|
#else
|
|
char buffer[MACLOGGER_BUFFER_SIZE];
|
|
size_t count = 0;
|
|
|
|
memset(buffer, 0, sizeof(buffer));
|
|
|
|
try {
|
|
count = maclogger_socket->recvFrom(
|
|
(void *) buffer,
|
|
sizeof(buffer) - 1);
|
|
} catch (...) {
|
|
LOG_WARN("MAC_logger socket error");
|
|
count = 0;
|
|
}
|
|
|
|
if (count) {
|
|
mclg_str.append(buffer, count);
|
|
parse_maclog();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//======================================================================
|
|
//
|
|
//======================================================================
|
|
void *maclogger_loop(void *args)
|
|
{
|
|
SET_THREAD_ID(MACLOGGER_TID);
|
|
|
|
LOG_INFO("%s", "MAC_logger loop started. ");
|
|
|
|
while(1) {
|
|
for (int i = 0; i < 100; i++) {
|
|
MilliSleep(10);
|
|
if (maclogger_exit) break;
|
|
}
|
|
if (maclogger_exit) break;
|
|
get_maclogger_udp();
|
|
}
|
|
// exit the maclogger thread
|
|
SET_THREAD_CANCEL();
|
|
return NULL;
|
|
}
|
|
|
|
//======================================================================
|
|
//
|
|
//======================================================================
|
|
bool maclogger_start(void)
|
|
{
|
|
maclogger_ip_address = "255.255.255.255";
|
|
maclogger_ip_port = "9932";
|
|
|
|
try {
|
|
maclogger_socket = new Socket(
|
|
Address( maclogger_ip_address.c_str(),
|
|
maclogger_ip_port.c_str(),
|
|
"udp") );
|
|
maclogger_socket->set_autoclose(true);
|
|
maclogger_socket->set_nonblocking(false);
|
|
maclogger_socket->bindUDP();
|
|
}
|
|
catch (const SocketException& e) {
|
|
LOG_ERROR(
|
|
"Could not resolve %s: %s",
|
|
maclogger_ip_address.c_str(),
|
|
e.what() );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//======================================================================
|
|
//
|
|
//======================================================================
|
|
void maclogger_init(void)
|
|
{
|
|
maclogger_enabled = false;
|
|
maclogger_exit = false;
|
|
|
|
if(!maclogger_start()) return;
|
|
|
|
LOG_INFO("%s", "UDP Init - OK");
|
|
|
|
if (pthread_create(&maclogger_thread, NULL, maclogger_loop, NULL) < 0) {
|
|
LOG_ERROR("MACLOGGER maclogger_thread: pthread_create failed");
|
|
return;
|
|
}
|
|
|
|
LOG_INFO("MACLOGGER thread started");
|
|
|
|
maclogger_enabled = true;
|
|
}
|
|
|
|
//======================================================================
|
|
//
|
|
//======================================================================
|
|
void maclogger_close(void)
|
|
{
|
|
if (!maclogger_enabled) return;
|
|
|
|
if(maclogger_socket) {
|
|
maclogger_socket->shut_down();
|
|
maclogger_socket->close();
|
|
}
|
|
|
|
maclogger_exit = true;
|
|
pthread_join(maclogger_thread, NULL);
|
|
|
|
LOG_INFO("%s", "MAC_logger loop terminated. ");
|
|
|
|
maclogger_enabled = false;
|
|
#ifdef TESTSTRINGS
|
|
tnbr = 0;
|
|
#endif
|
|
}
|
|
|