dl-fldigi/src/logbook/maclogger.cxx

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
}