Working through some common api commands
This commit is contained in:
parent
7037baa0a6
commit
f4688b44d3
@ -4,6 +4,7 @@
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QUdpSocket>
|
||||
#include <QHostInfo>
|
||||
#include <QTimer>
|
||||
@ -16,10 +17,66 @@
|
||||
|
||||
#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
|
||||
: public QUdpSocket
|
||||
{
|
||||
Q_OBJECT;
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
impl (QString const& id, QString const& version, QString const& revision,
|
||||
@ -84,6 +141,7 @@ public:
|
||||
QByteArray last_message_;
|
||||
};
|
||||
|
||||
|
||||
#include "MessageClient.moc"
|
||||
|
||||
void MessageClient::impl::host_info_results (QHostInfo host_info)
|
||||
@ -136,14 +194,26 @@ void MessageClient::impl::parse_message (QByteArray const& msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
QList<QByteArray> segments = msg.split('|');
|
||||
if(segments.isEmpty()){
|
||||
if(msg.isEmpty()){
|
||||
return;
|
||||
}
|
||||
|
||||
QString type(segments.first());
|
||||
QString message(segments.mid(1).join('|'));
|
||||
Q_EMIT self_->message_received(type, message);
|
||||
QJsonParseError e;
|
||||
QJsonDocument d = QJsonDocument::fromJson(msg, &e);
|
||||
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)
|
||||
{
|
||||
@ -159,8 +229,12 @@ void MessageClient::impl::heartbeat ()
|
||||
{
|
||||
if (server_port_ && !server_.isNull ())
|
||||
{
|
||||
QByteArray message("PING|");
|
||||
writeDatagram (message, server_, server_port_);
|
||||
Message m("PING", "", QMap<QString, QVariant>{
|
||||
{"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 ())
|
||||
{
|
||||
QByteArray message("EXIT|");
|
||||
writeDatagram (message, server_, server_port_);
|
||||
Message m("CLOSE");
|
||||
writeDatagram (m.toJson(), server_, server_port_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,7 +255,6 @@ void MessageClient::impl::send_message (QByteArray const& message)
|
||||
{
|
||||
if (message != last_message_) // avoid duplicates
|
||||
{
|
||||
qDebug() << "outgoing udp message" << message;
|
||||
writeDatagram (message, server_, server_port_);
|
||||
last_message_ = message;
|
||||
}
|
||||
@ -270,12 +343,8 @@ void MessageClient::set_server_port (port_type server_port)
|
||||
m_->server_port_ = server_port;
|
||||
}
|
||||
|
||||
void MessageClient::send_message(QString const &type, QString const &message){
|
||||
QByteArray b;
|
||||
b.append(type);
|
||||
b.append('|');
|
||||
b.append(message);
|
||||
m_->send_message(b);
|
||||
void MessageClient::send(Message const &message){
|
||||
m_->send_message(message.toJson());
|
||||
}
|
||||
|
||||
void MessageClient::send_raw_datagram (QByteArray const& message, QHostAddress const& dest_address
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <QTime>
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "Radio.hpp"
|
||||
#include "pimpl_h.hpp"
|
||||
@ -13,6 +15,29 @@ class QByteArray;
|
||||
class QHostAddress;
|
||||
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
|
||||
// matching server (MessageServer) at the other end of
|
||||
@ -24,7 +49,7 @@ class QColor;
|
||||
class MessageClient
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using Frequency = Radio::Frequency;
|
||||
@ -48,7 +73,7 @@ public:
|
||||
Q_SLOT void set_server_port (port_type server_port = 0u);
|
||||
|
||||
// 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
|
||||
// destination allowing the underlying socket to be used for general
|
||||
@ -59,6 +84,7 @@ public:
|
||||
// with send_raw_datagram() above)
|
||||
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
|
||||
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
|
||||
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
|
||||
// Hook up WSPR band hopping
|
||||
@ -1002,7 +1002,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
ui->dxCallEntry->clear();
|
||||
ui->dxGridEntry->clear();
|
||||
auto f = findFreeFreqOffset(500, 2000, 50);
|
||||
setFreqForRestore(f, false);
|
||||
setFreqOffsetForRestore(f, false);
|
||||
ui->cbVHFcontest->setChecked(false); // this needs to always be false
|
||||
|
||||
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 missingCallsign = selectedCall.isEmpty();
|
||||
if(!missingCallsign && m_callActivity.contains(selectedCall)){
|
||||
setFreqForRestore(m_callActivity[selectedCall].freq, true);
|
||||
setFreqOffsetForRestore(m_callActivity[selectedCall].freq, true);
|
||||
}
|
||||
|
||||
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 ()
|
||||
{
|
||||
Frequency dial_frequency {m_rigState.ptt () && m_rigState.split () ?
|
||||
m_rigState.tx_frequency () : m_rigState.frequency ()};
|
||||
auto dial_frequency = dialFrequency();
|
||||
|
||||
// lookup band
|
||||
auto const& band_name = m_config.bands ()->find (dial_frequency);
|
||||
@ -4440,11 +4444,7 @@ void MainWindow::stopTx()
|
||||
ui->extFreeTextMsgEdit->setReadOnly(false);
|
||||
update_dynamic_property(ui->extFreeTextMsgEdit, "transmitting", false);
|
||||
on_stopTxButton_clicked();
|
||||
|
||||
// if we have a previousFrequency, and should jump to it, do it
|
||||
if(m_previousFreq && m_shouldRestoreFreq){
|
||||
setFreqForRestore(m_previousFreq, false);
|
||||
}
|
||||
tryRestoreFreqOffset();
|
||||
}
|
||||
|
||||
ptt0Timer.start(200); //end-of-transmission sequencer delay
|
||||
@ -5571,6 +5571,12 @@ void MainWindow::displayTextForFreq(QString text, int freq, QDateTime date, bool
|
||||
if(newLine){
|
||||
block = -1;
|
||||
}
|
||||
|
||||
sendNetworkMessage("RECV", text, {
|
||||
{"UTC", QVariant(date.toSecsSinceEpoch())},
|
||||
{"OFFSET", QVariant(freq)},
|
||||
});
|
||||
|
||||
m_rxFrameBlockNumbers[freq] = writeMessageTextToUI(date, text, freq, bold, block);
|
||||
}
|
||||
|
||||
@ -5673,7 +5679,7 @@ void MainWindow::createMessageTransmitQueue(QString const& text){
|
||||
m_txFrameQueue.append(frames);
|
||||
m_txFrameCount = frames.length();
|
||||
|
||||
int freq = currentFreq();
|
||||
int freq = currentFreqOffset();
|
||||
|
||||
QStringList lines;
|
||||
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();
|
||||
}
|
||||
|
||||
@ -6041,7 +6047,7 @@ bool MainWindow::prepareNextMessageFrame()
|
||||
|
||||
bool MainWindow::isFreqOffsetFree(int f, int bw){
|
||||
// if this frequency is our current frequency, it's always "free"
|
||||
if(currentFreq() == f){
|
||||
if(currentFreqOffset() == f){
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6160,7 +6166,7 @@ void MainWindow::prepareBacon(){
|
||||
}
|
||||
|
||||
// Queue the beacon
|
||||
enqueueMessage(PriorityLow, lines.join(QChar('\n')), currentFreq(), [this](){
|
||||
enqueueMessage(PriorityLow, lines.join(QChar('\n')), currentFreqOffset(), [this](){
|
||||
m_nextBeaconQueued = false;
|
||||
});
|
||||
|
||||
@ -7184,7 +7190,7 @@ void MainWindow::on_tableWidgetRXAll_cellClicked(int row, int /*col*/){
|
||||
auto item = ui->tableWidgetRXAll->item(row, 0);
|
||||
int offset = item->text().toInt();
|
||||
|
||||
setFreqForRestore(offset, false);
|
||||
setFreqOffsetForRestore(offset, false);
|
||||
|
||||
ui->tableWidgetCalls->selectionModel()->select(
|
||||
ui->tableWidgetCalls->selectionModel()->selection(),
|
||||
@ -7244,7 +7250,7 @@ void MainWindow::on_tableWidgetCalls_cellClicked(int /*row*/, int /*col*/){
|
||||
}
|
||||
|
||||
auto d = m_callActivity[call];
|
||||
setFreqForRestore(d.freq, false);
|
||||
setFreqOffsetForRestore(d.freq, false);
|
||||
|
||||
ui->tableWidgetRXAll->selectionModel()->select(
|
||||
ui->tableWidgetRXAll->selectionModel()->selection(),
|
||||
@ -7443,7 +7449,7 @@ void MainWindow::setXIT(int n, Frequency base)
|
||||
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);
|
||||
if(shouldRestore){
|
||||
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)
|
||||
{
|
||||
if(rxFreq != txFreq){
|
||||
txFreq = rxFreq;
|
||||
}
|
||||
|
||||
m_previousFreq = currentFreq();
|
||||
m_previousFreq = currentFreqOffset();
|
||||
|
||||
if (ui->RxFreqSpinBox->isEnabled ()) ui->RxFreqSpinBox->setValue(rxFreq);
|
||||
ui->labDialFreqOffset->setText(QString("%1 Hz").arg(rxFreq));
|
||||
@ -8269,7 +8285,7 @@ void MainWindow::processRxActivity() {
|
||||
|
||||
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...
|
||||
// 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...
|
||||
int f = head.freq;
|
||||
if(f == -1){
|
||||
f = currentFreqOffset();
|
||||
}
|
||||
|
||||
if(!isFreqOffsetFree(f, 60)){
|
||||
f = findFreeFreqOffset(500, 2500, 60);
|
||||
}
|
||||
@ -8720,7 +8740,7 @@ void MainWindow::processTxQueue(){
|
||||
(ui->beaconButton->isChecked() && message.message.contains("BEACON"))
|
||||
){
|
||||
// then try to set the frequency...
|
||||
setFreqForRestore(f, true);
|
||||
setFreqOffsetForRestore(f, true);
|
||||
|
||||
// then prepare to transmit...
|
||||
toggleTx(true);
|
||||
@ -8940,30 +8960,101 @@ void MainWindow::postWSPRDecode (bool is_new, QStringList parts)
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::networkMessage(QString const &type, QString const &message)
|
||||
void MainWindow::networkMessage(Message const &message)
|
||||
{
|
||||
if(!m_config.accept_udp_requests()){
|
||||
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"){
|
||||
sendNetworkMessage("GRID", m_config.my_grid());
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Unable to process networkMessage:" << type;
|
||||
}
|
||||
|
||||
void MainWindow::sendNetworkMessage(QString const &type, QString const &message)
|
||||
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)
|
||||
{
|
||||
if(!m_config.accept_udp_requests()){
|
||||
return;
|
||||
}
|
||||
if (m_splash && m_splash->isVisible ()) m_splash->hide ();
|
||||
if (MessageBox::Retry == MessageBox::warning_message (this, tr ("Network Error")
|
||||
, tr ("Error: %1\nUDP server %2:%3")
|
||||
|
10
mainwindow.h
10
mainwindow.h
@ -43,6 +43,7 @@
|
||||
#include "qorderedmap.h"
|
||||
#include "qpriorityqueue.h"
|
||||
#include "varicode.h"
|
||||
#include "MessageClient.hpp"
|
||||
|
||||
#define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync
|
||||
#define NUM_JT65_SYMBOLS 126 //63 data + 63 sync
|
||||
@ -123,7 +124,8 @@ public slots:
|
||||
void readFromStdout();
|
||||
void p1ReadFromStdout();
|
||||
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 msgAvgDecode2();
|
||||
void fastPick(int x0, int x1, int y);
|
||||
@ -259,7 +261,7 @@ private slots:
|
||||
void on_freeTextMsg_currentTextChanged (QString const&);
|
||||
void on_nextFreeTextMsg_currentTextChanged (QString const&);
|
||||
void on_extFreeTextMsgEdit_currentTextChanged (QString const&);
|
||||
int currentFreq();
|
||||
int currentFreqOffset();
|
||||
int countFT8MessageFrames(QString const& text);
|
||||
QStringList buildFT8MessageFrames(QString const& text);
|
||||
QString parseFT8Message(QString input, bool *isFree);
|
||||
@ -313,8 +315,9 @@ private slots:
|
||||
void on_cbCQonly_toggled(bool b);
|
||||
void on_cbFirst_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, const QMap<QString, QVariant> ¶ms);
|
||||
void networkError (QString const&);
|
||||
void on_ClrAvgButton_clicked();
|
||||
void on_syncSpinBox_valueChanged(int n);
|
||||
@ -811,6 +814,7 @@ private:
|
||||
void pskSetLocal ();
|
||||
void pskPost(DecodedText const& decodedtext);
|
||||
void pskLogReport(QString mode, int offset, int snr, QString callsign, QString grid);
|
||||
Radio::Frequency dialFrequency();
|
||||
void displayDialFrequency ();
|
||||
void transmitDisplay (bool);
|
||||
void processMessage(DecodedText const&, Qt::KeyboardModifiers = 0);
|
||||
|
104
udp.py
104
udp.py
@ -1,39 +1,97 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import json
|
||||
from socket import socket, AF_INET, SOCK_DGRAM
|
||||
import time
|
||||
|
||||
listen = ('127.0.0.1', 2237)
|
||||
|
||||
def main():
|
||||
sock = socket(AF_INET, SOCK_DGRAM)
|
||||
print("listening on", ':'.join(map(str, listen)))
|
||||
sock.bind(listen)
|
||||
|
||||
def from_message(content):
|
||||
try:
|
||||
while True:
|
||||
content, addr = sock.recvfrom(65500)
|
||||
print("from:", ":".join(map(str, addr)))
|
||||
return json.loads(content)
|
||||
except ValueError:
|
||||
return {}
|
||||
|
||||
typ, msg = content.split('|')
|
||||
print("->", typ)
|
||||
print("->", msg)
|
||||
|
||||
if typ == "PING":
|
||||
print("sending pong reply...", end="")
|
||||
sock.sendto("PONG", addr)
|
||||
print("done")
|
||||
def to_message(typ, value='', params=None):
|
||||
if params is None:
|
||||
params = {}
|
||||
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":
|
||||
break
|
||||
finally:
|
||||
sock.close()
|
||||
class Server(object):
|
||||
|
||||
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:
|
||||
self.sock.close()
|
||||
|
||||
def close(self):
|
||||
self.listening = False
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
s = Server()
|
||||
s.listen()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
Loading…
Reference in New Issue
Block a user