Working through some common api commands
This commit is contained in:
parent
7037baa0a6
commit
f4688b44d3
@ -4,6 +4,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QUdpSocket>
|
#include <QUdpSocket>
|
||||||
#include <QHostInfo>
|
#include <QHostInfo>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@ -16,10 +17,66 @@
|
|||||||
|
|
||||||
#include "moc_MessageClient.cpp"
|
#include "moc_MessageClient.cpp"
|
||||||
|
|
||||||
|
Message::Message()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Message(QString const &type, QString const &value):
|
||||||
|
type_{ type },
|
||||||
|
value_{ value }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Message(QString const &type, QString const &value, QMap<QString, QVariant> const ¶ms):
|
||||||
|
type_{ type },
|
||||||
|
value_{ value },
|
||||||
|
params_{ params }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Message::read(const QJsonObject &json){
|
||||||
|
if(json.contains("type") && json["type"].isString()){
|
||||||
|
type_ = json["type"].toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(json.contains("value") && json["value"].isString()){
|
||||||
|
value_ = json["value"].toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(json.contains("params") && json["params"].isObject()){
|
||||||
|
params_.clear();
|
||||||
|
|
||||||
|
QJsonObject params = json["params"].toObject();
|
||||||
|
foreach(auto key, params.keys()){
|
||||||
|
params_[key] = params[key].toVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Message::write(QJsonObject &json) const{
|
||||||
|
json["type"] = type_;
|
||||||
|
json["value"] = value_;
|
||||||
|
|
||||||
|
QJsonObject params;
|
||||||
|
foreach(auto key, params_.keys()){
|
||||||
|
params.insert(key, QJsonValue::fromVariant(params_[key]));
|
||||||
|
}
|
||||||
|
json["params"] = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Message::toJson() const {
|
||||||
|
QJsonObject o;
|
||||||
|
write(o);
|
||||||
|
|
||||||
|
QJsonDocument d(o);
|
||||||
|
return d.toJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class MessageClient::impl
|
class MessageClient::impl
|
||||||
: public QUdpSocket
|
: public QUdpSocket
|
||||||
{
|
{
|
||||||
Q_OBJECT;
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
impl (QString const& id, QString const& version, QString const& revision,
|
impl (QString const& id, QString const& version, QString const& revision,
|
||||||
@ -84,6 +141,7 @@ public:
|
|||||||
QByteArray last_message_;
|
QByteArray last_message_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#include "MessageClient.moc"
|
#include "MessageClient.moc"
|
||||||
|
|
||||||
void MessageClient::impl::host_info_results (QHostInfo host_info)
|
void MessageClient::impl::host_info_results (QHostInfo host_info)
|
||||||
@ -136,14 +194,26 @@ void MessageClient::impl::parse_message (QByteArray const& msg)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
QList<QByteArray> segments = msg.split('|');
|
if(msg.isEmpty()){
|
||||||
if(segments.isEmpty()){
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString type(segments.first());
|
QJsonParseError e;
|
||||||
QString message(segments.mid(1).join('|'));
|
QJsonDocument d = QJsonDocument::fromJson(msg, &e);
|
||||||
Q_EMIT self_->message_received(type, message);
|
if(e.error != QJsonParseError::NoError){
|
||||||
|
Q_EMIT self_->error(QString {"MessageClient json parse error: %1"}.arg(e.errorString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!d.isObject()){
|
||||||
|
Q_EMIT self_->error(QString {"MessageClient json parse error: json is not an object"});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Message m;
|
||||||
|
m.read(d.object());
|
||||||
|
Q_EMIT self_->message(m);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (std::exception const& e)
|
catch (std::exception const& e)
|
||||||
{
|
{
|
||||||
@ -159,8 +229,12 @@ void MessageClient::impl::heartbeat ()
|
|||||||
{
|
{
|
||||||
if (server_port_ && !server_.isNull ())
|
if (server_port_ && !server_.isNull ())
|
||||||
{
|
{
|
||||||
QByteArray message("PING|");
|
Message m("PING", "", QMap<QString, QVariant>{
|
||||||
writeDatagram (message, server_, server_port_);
|
{"NAME", QVariant(QApplication::applicationName())},
|
||||||
|
{"VERSION", QVariant(QApplication::applicationVersion())},
|
||||||
|
{"UTC", QVariant(QDateTime::currentDateTimeUtc().toSecsSinceEpoch())}
|
||||||
|
});
|
||||||
|
writeDatagram (m.toJson(), server_, server_port_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,8 +242,8 @@ void MessageClient::impl::closedown ()
|
|||||||
{
|
{
|
||||||
if (server_port_ && !server_.isNull ())
|
if (server_port_ && !server_.isNull ())
|
||||||
{
|
{
|
||||||
QByteArray message("EXIT|");
|
Message m("CLOSE");
|
||||||
writeDatagram (message, server_, server_port_);
|
writeDatagram (m.toJson(), server_, server_port_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +255,6 @@ void MessageClient::impl::send_message (QByteArray const& message)
|
|||||||
{
|
{
|
||||||
if (message != last_message_) // avoid duplicates
|
if (message != last_message_) // avoid duplicates
|
||||||
{
|
{
|
||||||
qDebug() << "outgoing udp message" << message;
|
|
||||||
writeDatagram (message, server_, server_port_);
|
writeDatagram (message, server_, server_port_);
|
||||||
last_message_ = message;
|
last_message_ = message;
|
||||||
}
|
}
|
||||||
@ -270,12 +343,8 @@ void MessageClient::set_server_port (port_type server_port)
|
|||||||
m_->server_port_ = server_port;
|
m_->server_port_ = server_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageClient::send_message(QString const &type, QString const &message){
|
void MessageClient::send(Message const &message){
|
||||||
QByteArray b;
|
m_->send_message(message.toJson());
|
||||||
b.append(type);
|
|
||||||
b.append('|');
|
|
||||||
b.append(message);
|
|
||||||
m_->send_message(b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageClient::send_raw_datagram (QByteArray const& message, QHostAddress const& dest_address
|
void MessageClient::send_raw_datagram (QByteArray const& message, QHostAddress const& dest_address
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include <QTime>
|
#include <QTime>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
#include "Radio.hpp"
|
#include "Radio.hpp"
|
||||||
#include "pimpl_h.hpp"
|
#include "pimpl_h.hpp"
|
||||||
@ -13,6 +15,29 @@ class QByteArray;
|
|||||||
class QHostAddress;
|
class QHostAddress;
|
||||||
class QColor;
|
class QColor;
|
||||||
|
|
||||||
|
|
||||||
|
class Message {
|
||||||
|
public:
|
||||||
|
Message();
|
||||||
|
Message(QString const &type, QString const &value="");
|
||||||
|
Message(QString const &type, QString const &value, QMap<QString, QVariant> const ¶ms);
|
||||||
|
|
||||||
|
void read(const QJsonObject &json);
|
||||||
|
void write(QJsonObject &json) const;
|
||||||
|
|
||||||
|
QByteArray toJson() const;
|
||||||
|
|
||||||
|
QString type() const { return type_; }
|
||||||
|
QString value() const { return value_; }
|
||||||
|
QMap<QString, QVariant> params() const { return params_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString type_;
|
||||||
|
QString value_;
|
||||||
|
QMap<QString, QVariant> params_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// MessageClient - Manage messages sent and replies received from a
|
// MessageClient - Manage messages sent and replies received from a
|
||||||
// matching server (MessageServer) at the other end of
|
// matching server (MessageServer) at the other end of
|
||||||
@ -24,7 +49,7 @@ class QColor;
|
|||||||
class MessageClient
|
class MessageClient
|
||||||
: public QObject
|
: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT;
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Frequency = Radio::Frequency;
|
using Frequency = Radio::Frequency;
|
||||||
@ -48,7 +73,7 @@ public:
|
|||||||
Q_SLOT void set_server_port (port_type server_port = 0u);
|
Q_SLOT void set_server_port (port_type server_port = 0u);
|
||||||
|
|
||||||
// this slot is used to send an arbitrary message
|
// this slot is used to send an arbitrary message
|
||||||
Q_SLOT void send_message(QString const &type, QString const &message);
|
Q_SLOT void send(Message const &message);
|
||||||
|
|
||||||
// this slot may be used to send arbitrary UDP datagrams to and
|
// this slot may be used to send arbitrary UDP datagrams to and
|
||||||
// destination allowing the underlying socket to be used for general
|
// destination allowing the underlying socket to be used for general
|
||||||
@ -59,6 +84,7 @@ public:
|
|||||||
// with send_raw_datagram() above)
|
// with send_raw_datagram() above)
|
||||||
Q_SLOT void add_blocked_destination (QHostAddress const&);
|
Q_SLOT void add_blocked_destination (QHostAddress const&);
|
||||||
|
|
||||||
|
Q_SIGNAL void message(Message const &message);
|
||||||
|
|
||||||
// this signal is emitted when the a reply a message is received
|
// this signal is emitted when the a reply a message is received
|
||||||
Q_SIGNAL void message_received(QString const &type, QString const &message);
|
Q_SIGNAL void message_received(QString const &type, QString const &message);
|
||||||
|
139
mainwindow.cpp
139
mainwindow.cpp
@ -547,7 +547,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
|
|
||||||
// Network message handlers
|
// Network message handlers
|
||||||
connect (m_messageClient, &MessageClient::error, this, &MainWindow::networkError);
|
connect (m_messageClient, &MessageClient::error, this, &MainWindow::networkError);
|
||||||
connect (m_messageClient, &MessageClient::message_received, this, &MainWindow::networkMessage);
|
connect (m_messageClient, &MessageClient::message, this, &MainWindow::networkMessage);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Hook up WSPR band hopping
|
// Hook up WSPR band hopping
|
||||||
@ -1002,7 +1002,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
ui->dxCallEntry->clear();
|
ui->dxCallEntry->clear();
|
||||||
ui->dxGridEntry->clear();
|
ui->dxGridEntry->clear();
|
||||||
auto f = findFreeFreqOffset(500, 2000, 50);
|
auto f = findFreeFreqOffset(500, 2000, 50);
|
||||||
setFreqForRestore(f, false);
|
setFreqOffsetForRestore(f, false);
|
||||||
ui->cbVHFcontest->setChecked(false); // this needs to always be false
|
ui->cbVHFcontest->setChecked(false); // this needs to always be false
|
||||||
|
|
||||||
ui->spotButton->setChecked(m_config.spot_to_psk_reporter());
|
ui->spotButton->setChecked(m_config.spot_to_psk_reporter());
|
||||||
@ -1117,7 +1117,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
bool isAllCall = isAllCallIncluded(selectedCall);
|
bool isAllCall = isAllCallIncluded(selectedCall);
|
||||||
bool missingCallsign = selectedCall.isEmpty();
|
bool missingCallsign = selectedCall.isEmpty();
|
||||||
if(!missingCallsign && m_callActivity.contains(selectedCall)){
|
if(!missingCallsign && m_callActivity.contains(selectedCall)){
|
||||||
setFreqForRestore(m_callActivity[selectedCall].freq, true);
|
setFreqOffsetForRestore(m_callActivity[selectedCall].freq, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto directedMenu = menu->addMenu("Directed");
|
auto directedMenu = menu->addMenu("Directed");
|
||||||
@ -2192,10 +2192,14 @@ void MainWindow::bumpFqso(int n) //bumpFqso()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Radio::Frequency MainWindow::dialFrequency() {
|
||||||
|
return Frequency {m_rigState.ptt () && m_rigState.split () ?
|
||||||
|
m_rigState.tx_frequency () : m_rigState.frequency ()};
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::displayDialFrequency ()
|
void MainWindow::displayDialFrequency ()
|
||||||
{
|
{
|
||||||
Frequency dial_frequency {m_rigState.ptt () && m_rigState.split () ?
|
auto dial_frequency = dialFrequency();
|
||||||
m_rigState.tx_frequency () : m_rigState.frequency ()};
|
|
||||||
|
|
||||||
// lookup band
|
// lookup band
|
||||||
auto const& band_name = m_config.bands ()->find (dial_frequency);
|
auto const& band_name = m_config.bands ()->find (dial_frequency);
|
||||||
@ -4440,11 +4444,7 @@ void MainWindow::stopTx()
|
|||||||
ui->extFreeTextMsgEdit->setReadOnly(false);
|
ui->extFreeTextMsgEdit->setReadOnly(false);
|
||||||
update_dynamic_property(ui->extFreeTextMsgEdit, "transmitting", false);
|
update_dynamic_property(ui->extFreeTextMsgEdit, "transmitting", false);
|
||||||
on_stopTxButton_clicked();
|
on_stopTxButton_clicked();
|
||||||
|
tryRestoreFreqOffset();
|
||||||
// if we have a previousFrequency, and should jump to it, do it
|
|
||||||
if(m_previousFreq && m_shouldRestoreFreq){
|
|
||||||
setFreqForRestore(m_previousFreq, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ptt0Timer.start(200); //end-of-transmission sequencer delay
|
ptt0Timer.start(200); //end-of-transmission sequencer delay
|
||||||
@ -5571,6 +5571,12 @@ void MainWindow::displayTextForFreq(QString text, int freq, QDateTime date, bool
|
|||||||
if(newLine){
|
if(newLine){
|
||||||
block = -1;
|
block = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendNetworkMessage("RECV", text, {
|
||||||
|
{"UTC", QVariant(date.toSecsSinceEpoch())},
|
||||||
|
{"OFFSET", QVariant(freq)},
|
||||||
|
});
|
||||||
|
|
||||||
m_rxFrameBlockNumbers[freq] = writeMessageTextToUI(date, text, freq, bold, block);
|
m_rxFrameBlockNumbers[freq] = writeMessageTextToUI(date, text, freq, bold, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5673,7 +5679,7 @@ void MainWindow::createMessageTransmitQueue(QString const& text){
|
|||||||
m_txFrameQueue.append(frames);
|
m_txFrameQueue.append(frames);
|
||||||
m_txFrameCount = frames.length();
|
m_txFrameCount = frames.length();
|
||||||
|
|
||||||
int freq = currentFreq();
|
int freq = currentFreqOffset();
|
||||||
|
|
||||||
QStringList lines;
|
QStringList lines;
|
||||||
foreach(auto frame, frames){
|
foreach(auto frame, frames){
|
||||||
@ -5743,7 +5749,7 @@ void MainWindow::on_extFreeTextMsgEdit_currentTextChanged (QString const& text)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int MainWindow::currentFreq(){
|
int MainWindow::currentFreqOffset(){
|
||||||
return ui->RxFreqSpinBox->value();
|
return ui->RxFreqSpinBox->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6041,7 +6047,7 @@ bool MainWindow::prepareNextMessageFrame()
|
|||||||
|
|
||||||
bool MainWindow::isFreqOffsetFree(int f, int bw){
|
bool MainWindow::isFreqOffsetFree(int f, int bw){
|
||||||
// if this frequency is our current frequency, it's always "free"
|
// if this frequency is our current frequency, it's always "free"
|
||||||
if(currentFreq() == f){
|
if(currentFreqOffset() == f){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6160,7 +6166,7 @@ void MainWindow::prepareBacon(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Queue the beacon
|
// Queue the beacon
|
||||||
enqueueMessage(PriorityLow, lines.join(QChar('\n')), currentFreq(), [this](){
|
enqueueMessage(PriorityLow, lines.join(QChar('\n')), currentFreqOffset(), [this](){
|
||||||
m_nextBeaconQueued = false;
|
m_nextBeaconQueued = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -7184,7 +7190,7 @@ void MainWindow::on_tableWidgetRXAll_cellClicked(int row, int /*col*/){
|
|||||||
auto item = ui->tableWidgetRXAll->item(row, 0);
|
auto item = ui->tableWidgetRXAll->item(row, 0);
|
||||||
int offset = item->text().toInt();
|
int offset = item->text().toInt();
|
||||||
|
|
||||||
setFreqForRestore(offset, false);
|
setFreqOffsetForRestore(offset, false);
|
||||||
|
|
||||||
ui->tableWidgetCalls->selectionModel()->select(
|
ui->tableWidgetCalls->selectionModel()->select(
|
||||||
ui->tableWidgetCalls->selectionModel()->selection(),
|
ui->tableWidgetCalls->selectionModel()->selection(),
|
||||||
@ -7244,7 +7250,7 @@ void MainWindow::on_tableWidgetCalls_cellClicked(int /*row*/, int /*col*/){
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto d = m_callActivity[call];
|
auto d = m_callActivity[call];
|
||||||
setFreqForRestore(d.freq, false);
|
setFreqOffsetForRestore(d.freq, false);
|
||||||
|
|
||||||
ui->tableWidgetRXAll->selectionModel()->select(
|
ui->tableWidgetRXAll->selectionModel()->select(
|
||||||
ui->tableWidgetRXAll->selectionModel()->selection(),
|
ui->tableWidgetRXAll->selectionModel()->selection(),
|
||||||
@ -7443,7 +7449,7 @@ void MainWindow::setXIT(int n, Frequency base)
|
|||||||
Q_EMIT transmitFrequency (ui->TxFreqSpinBox->value () - m_XIT);
|
Q_EMIT transmitFrequency (ui->TxFreqSpinBox->value () - m_XIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::setFreqForRestore(int freq, bool shouldRestore){
|
void MainWindow::setFreqOffsetForRestore(int freq, bool shouldRestore){
|
||||||
setFreq4(freq, freq);
|
setFreq4(freq, freq);
|
||||||
if(shouldRestore){
|
if(shouldRestore){
|
||||||
m_shouldRestoreFreq = true;
|
m_shouldRestoreFreq = true;
|
||||||
@ -7453,13 +7459,23 @@ void MainWindow::setFreqForRestore(int freq, bool shouldRestore){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MainWindow::tryRestoreFreqOffset(){
|
||||||
|
if(!m_shouldRestoreFreq || m_previousFreq == 0){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFreqOffsetForRestore(m_previousFreq, false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::setFreq4(int rxFreq, int txFreq)
|
void MainWindow::setFreq4(int rxFreq, int txFreq)
|
||||||
{
|
{
|
||||||
if(rxFreq != txFreq){
|
if(rxFreq != txFreq){
|
||||||
txFreq = rxFreq;
|
txFreq = rxFreq;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_previousFreq = currentFreq();
|
m_previousFreq = currentFreqOffset();
|
||||||
|
|
||||||
if (ui->RxFreqSpinBox->isEnabled ()) ui->RxFreqSpinBox->setValue(rxFreq);
|
if (ui->RxFreqSpinBox->isEnabled ()) ui->RxFreqSpinBox->setValue(rxFreq);
|
||||||
ui->labDialFreqOffset->setText(QString("%1 Hz").arg(rxFreq));
|
ui->labDialFreqOffset->setText(QString("%1 Hz").arg(rxFreq));
|
||||||
@ -8269,7 +8285,7 @@ void MainWindow::processRxActivity() {
|
|||||||
|
|
||||||
int freq = d.freq / 10 * 10;
|
int freq = d.freq / 10 * 10;
|
||||||
|
|
||||||
bool shouldDisplay = abs(freq - currentFreq()) <= 10;
|
bool shouldDisplay = abs(freq - currentFreqOffset()) <= 10;
|
||||||
|
|
||||||
// if this is a (recent) directed offset, bump the cache, and display...
|
// if this is a (recent) directed offset, bump the cache, and display...
|
||||||
// this will allow a directed free text command followed by non-buffered data frames.
|
// this will allow a directed free text command followed by non-buffered data frames.
|
||||||
@ -8684,6 +8700,10 @@ void MainWindow::processTxQueue(){
|
|||||||
|
|
||||||
// decide if it's ok to transmit...
|
// decide if it's ok to transmit...
|
||||||
int f = head.freq;
|
int f = head.freq;
|
||||||
|
if(f == -1){
|
||||||
|
f = currentFreqOffset();
|
||||||
|
}
|
||||||
|
|
||||||
if(!isFreqOffsetFree(f, 60)){
|
if(!isFreqOffsetFree(f, 60)){
|
||||||
f = findFreeFreqOffset(500, 2500, 60);
|
f = findFreeFreqOffset(500, 2500, 60);
|
||||||
}
|
}
|
||||||
@ -8720,7 +8740,7 @@ void MainWindow::processTxQueue(){
|
|||||||
(ui->beaconButton->isChecked() && message.message.contains("BEACON"))
|
(ui->beaconButton->isChecked() && message.message.contains("BEACON"))
|
||||||
){
|
){
|
||||||
// then try to set the frequency...
|
// then try to set the frequency...
|
||||||
setFreqForRestore(f, true);
|
setFreqOffsetForRestore(f, true);
|
||||||
|
|
||||||
// then prepare to transmit...
|
// then prepare to transmit...
|
||||||
toggleTx(true);
|
toggleTx(true);
|
||||||
@ -8940,30 +8960,101 @@ void MainWindow::postWSPRDecode (bool is_new, QStringList parts)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::networkMessage(QString const &type, QString const &message)
|
void MainWindow::networkMessage(Message const &message)
|
||||||
{
|
{
|
||||||
if(!m_config.accept_udp_requests()){
|
if(!m_config.accept_udp_requests()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto type = message.type();
|
||||||
|
|
||||||
|
if(type == "PONG"){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type == "GET_CALL_ACTIVITY"){
|
||||||
|
QMap<QString, QVariant> calls;
|
||||||
|
foreach(auto cd, m_callActivity.values()){
|
||||||
|
QMap<QString, QVariant> detail;
|
||||||
|
detail["SNR"] = QVariant(cd.snr);
|
||||||
|
detail["GRID"] = QVariant(cd.grid);
|
||||||
|
detail["UTC"] = QVariant(cd.utcTimestamp.toSecsSinceEpoch());
|
||||||
|
calls[cd.call] = QVariant(detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendNetworkMessage("CALL_ACTIVITY", "", calls);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type == "GET_CALLSIGN"){
|
||||||
|
sendNetworkMessage("CALLSIGN", m_config.my_callsign());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(type == "GET_GRID"){
|
if(type == "GET_GRID"){
|
||||||
sendNetworkMessage("GRID", m_config.my_grid());
|
sendNetworkMessage("GRID", m_config.my_grid());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == "SET_GRID"){
|
if(type == "SET_GRID"){
|
||||||
m_config.set_location(message);
|
m_config.set_location(message.value());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type == "GET_FREQ"){
|
||||||
|
sendNetworkMessage("FREQ", "", {
|
||||||
|
{"DIAL", QVariant((quint64)dialFrequency())},
|
||||||
|
{"OFFSET", QVariant((quint64)currentFreqOffset())}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type == "SET_FREQ"){
|
||||||
|
auto params = message.params();
|
||||||
|
if(params.contains("DIAL")){
|
||||||
|
bool ok = false;
|
||||||
|
auto f = params["DIAL"].toInt(&ok);
|
||||||
|
if(ok){
|
||||||
|
setRig(f);
|
||||||
|
displayDialFrequency();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(params.contains("OFFSET")){
|
||||||
|
bool ok = false;
|
||||||
|
auto f = params["OFFSET"].toInt(&ok);
|
||||||
|
if(ok){
|
||||||
|
setFreqOffsetForRestore(f, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type == "SEND_MESSAGE"){
|
||||||
|
auto text = message.value();
|
||||||
|
if(!text.isEmpty()){
|
||||||
|
enqueueMessage(PriorityNormal, text, -1, nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::sendNetworkMessage(QString const &type, QString const &message)
|
qDebug() << "Unable to process networkMessage:" << type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::sendNetworkMessage(QString const &type, QString const &message){
|
||||||
|
m_messageClient->send(Message(type, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::sendNetworkMessage(QString const &type, QString const &message, QMap<QString, QVariant> const ¶ms)
|
||||||
{
|
{
|
||||||
m_messageClient->send_message(type, message);
|
m_messageClient->send(Message(type, message, params));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::networkError (QString const& e)
|
void MainWindow::networkError (QString const& e)
|
||||||
{
|
{
|
||||||
|
if(!m_config.accept_udp_requests()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (m_splash && m_splash->isVisible ()) m_splash->hide ();
|
if (m_splash && m_splash->isVisible ()) m_splash->hide ();
|
||||||
if (MessageBox::Retry == MessageBox::warning_message (this, tr ("Network Error")
|
if (MessageBox::Retry == MessageBox::warning_message (this, tr ("Network Error")
|
||||||
, tr ("Error: %1\nUDP server %2:%3")
|
, tr ("Error: %1\nUDP server %2:%3")
|
||||||
|
10
mainwindow.h
10
mainwindow.h
@ -43,6 +43,7 @@
|
|||||||
#include "qorderedmap.h"
|
#include "qorderedmap.h"
|
||||||
#include "qpriorityqueue.h"
|
#include "qpriorityqueue.h"
|
||||||
#include "varicode.h"
|
#include "varicode.h"
|
||||||
|
#include "MessageClient.hpp"
|
||||||
|
|
||||||
#define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync
|
#define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync
|
||||||
#define NUM_JT65_SYMBOLS 126 //63 data + 63 sync
|
#define NUM_JT65_SYMBOLS 126 //63 data + 63 sync
|
||||||
@ -123,7 +124,8 @@ public slots:
|
|||||||
void readFromStdout();
|
void readFromStdout();
|
||||||
void p1ReadFromStdout();
|
void p1ReadFromStdout();
|
||||||
void setXIT(int n, Frequency base = 0u);
|
void setXIT(int n, Frequency base = 0u);
|
||||||
void setFreqForRestore(int freq, bool shouldRestore);
|
void setFreqOffsetForRestore(int freq, bool shouldRestore);
|
||||||
|
bool tryRestoreFreqOffset();
|
||||||
void setFreq4(int rxFreq, int txFreq);
|
void setFreq4(int rxFreq, int txFreq);
|
||||||
void msgAvgDecode2();
|
void msgAvgDecode2();
|
||||||
void fastPick(int x0, int x1, int y);
|
void fastPick(int x0, int x1, int y);
|
||||||
@ -259,7 +261,7 @@ private slots:
|
|||||||
void on_freeTextMsg_currentTextChanged (QString const&);
|
void on_freeTextMsg_currentTextChanged (QString const&);
|
||||||
void on_nextFreeTextMsg_currentTextChanged (QString const&);
|
void on_nextFreeTextMsg_currentTextChanged (QString const&);
|
||||||
void on_extFreeTextMsgEdit_currentTextChanged (QString const&);
|
void on_extFreeTextMsgEdit_currentTextChanged (QString const&);
|
||||||
int currentFreq();
|
int currentFreqOffset();
|
||||||
int countFT8MessageFrames(QString const& text);
|
int countFT8MessageFrames(QString const& text);
|
||||||
QStringList buildFT8MessageFrames(QString const& text);
|
QStringList buildFT8MessageFrames(QString const& text);
|
||||||
QString parseFT8Message(QString input, bool *isFree);
|
QString parseFT8Message(QString input, bool *isFree);
|
||||||
@ -313,8 +315,9 @@ private slots:
|
|||||||
void on_cbCQonly_toggled(bool b);
|
void on_cbCQonly_toggled(bool b);
|
||||||
void on_cbFirst_toggled(bool b);
|
void on_cbFirst_toggled(bool b);
|
||||||
void on_cbAutoSeq_toggled(bool b);
|
void on_cbAutoSeq_toggled(bool b);
|
||||||
void networkMessage(QString const &type, QString const &message);
|
void networkMessage(Message const &message);
|
||||||
void sendNetworkMessage(QString const &type, QString const &message);
|
void sendNetworkMessage(QString const &type, QString const &message);
|
||||||
|
void sendNetworkMessage(QString const &type, QString const &message, const QMap<QString, QVariant> ¶ms);
|
||||||
void networkError (QString const&);
|
void networkError (QString const&);
|
||||||
void on_ClrAvgButton_clicked();
|
void on_ClrAvgButton_clicked();
|
||||||
void on_syncSpinBox_valueChanged(int n);
|
void on_syncSpinBox_valueChanged(int n);
|
||||||
@ -811,6 +814,7 @@ private:
|
|||||||
void pskSetLocal ();
|
void pskSetLocal ();
|
||||||
void pskPost(DecodedText const& decodedtext);
|
void pskPost(DecodedText const& decodedtext);
|
||||||
void pskLogReport(QString mode, int offset, int snr, QString callsign, QString grid);
|
void pskLogReport(QString mode, int offset, int snr, QString callsign, QString grid);
|
||||||
|
Radio::Frequency dialFrequency();
|
||||||
void displayDialFrequency ();
|
void displayDialFrequency ();
|
||||||
void transmitDisplay (bool);
|
void transmitDisplay (bool);
|
||||||
void processMessage(DecodedText const&, Qt::KeyboardModifiers = 0);
|
void processMessage(DecodedText const&, Qt::KeyboardModifiers = 0);
|
||||||
|
102
udp.py
102
udp.py
@ -1,39 +1,97 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import json
|
||||||
from socket import socket, AF_INET, SOCK_DGRAM
|
from socket import socket, AF_INET, SOCK_DGRAM
|
||||||
import time
|
import time
|
||||||
|
|
||||||
listen = ('127.0.0.1', 2237)
|
listen = ('127.0.0.1', 2237)
|
||||||
|
|
||||||
def main():
|
|
||||||
sock = socket(AF_INET, SOCK_DGRAM)
|
def from_message(content):
|
||||||
print("listening on", ':'.join(map(str, listen)))
|
|
||||||
sock.bind(listen)
|
|
||||||
try:
|
try:
|
||||||
while True:
|
return json.loads(content)
|
||||||
content, addr = sock.recvfrom(65500)
|
except ValueError:
|
||||||
print("from:", ":".join(map(str, addr)))
|
return {}
|
||||||
|
|
||||||
typ, msg = content.split('|')
|
|
||||||
print("->", typ)
|
|
||||||
print("->", msg)
|
|
||||||
|
|
||||||
if typ == "PING":
|
def to_message(typ, value='', params=None):
|
||||||
print("sending pong reply...", end="")
|
if params is None:
|
||||||
sock.sendto("PONG", addr)
|
params = {}
|
||||||
print("done")
|
return json.dumps({'type': typ, 'value': value, 'params': params})
|
||||||
|
|
||||||
sock.sendto("SET_GRID|EM73NA99", addr)
|
|
||||||
time.sleep(1)
|
|
||||||
sock.sendto("SET_GRID|EM73NA98", addr)
|
|
||||||
time.sleep(1)
|
|
||||||
sock.sendto("SET_GRID|EM73NA97", addr)
|
|
||||||
|
|
||||||
if typ == "EXIT":
|
class Server(object):
|
||||||
break
|
|
||||||
|
def process(self, message):
|
||||||
|
typ = message.get('type', '')
|
||||||
|
value = message.get('value', '')
|
||||||
|
params = message.get('params', {})
|
||||||
|
if not typ:
|
||||||
|
return
|
||||||
|
|
||||||
|
print('->', typ)
|
||||||
|
|
||||||
|
if value:
|
||||||
|
print('-> value', value)
|
||||||
|
|
||||||
|
if params:
|
||||||
|
print('-> params: ', params)
|
||||||
|
|
||||||
|
if typ == 'PING':
|
||||||
|
self.send('GET_GRID')
|
||||||
|
self.send('GET_FREQ')
|
||||||
|
self.send('GET_CALLSIGN')
|
||||||
|
self.send('GET_CALL_ACTIVITY')
|
||||||
|
|
||||||
|
#### elif typ == 'GRID':
|
||||||
|
#### if value != 'EM73TU49TQ':
|
||||||
|
#### self.send('SET_GRID', 'EM73TU49TQ')
|
||||||
|
|
||||||
|
#### elif typ == 'FREQ':
|
||||||
|
#### if params.get('DIAL', 0) != 14064000:
|
||||||
|
#### self.send('SET_FREQ', '', {"DIAL": 14064000, "OFFSET": 977})
|
||||||
|
#### self.send('SEND_MESSAGE', 'HELLO WORLD')
|
||||||
|
|
||||||
|
elif typ == 'CLOSE':
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def send(self, *args, **kwargs):
|
||||||
|
message = to_message(*args, **kwargs)
|
||||||
|
print('outgoing message:', message)
|
||||||
|
self.sock.sendto(message, self.reply_to)
|
||||||
|
|
||||||
|
def listen(self):
|
||||||
|
print('listening on', ':'.join(map(str, listen)))
|
||||||
|
self.sock = socket(AF_INET, SOCK_DGRAM)
|
||||||
|
self.sock.bind(listen)
|
||||||
|
self.listening = True
|
||||||
|
try:
|
||||||
|
while self.listening:
|
||||||
|
content, addr = self.sock.recvfrom(65500)
|
||||||
|
print('incoming message:', ':'.join(map(str, addr)))
|
||||||
|
|
||||||
|
try:
|
||||||
|
message = json.loads(content)
|
||||||
|
except ValueError:
|
||||||
|
message = {}
|
||||||
|
|
||||||
|
if not message:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.reply_to = addr
|
||||||
|
self.process(message)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
sock.close()
|
self.sock.close()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.listening = False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
s = Server()
|
||||||
|
s.listen()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
Loading…
Reference in New Issue
Block a user