This commit is contained in:
AlexandreRouma 2023-02-07 12:04:29 +01:00
parent 0a6fbdb393
commit 208851ebc5
3 changed files with 657 additions and 13 deletions

View File

@ -0,0 +1,318 @@
#include "rigctl.h"
namespace net::rigctl {
Client::Client(std::shared_ptr<Socket> sock) {
this->sock = sock;
}
Client::~Client() {
close();
}
bool Client::isOpen() {
return sock->isOpen();
}
void Client::close() {
sock->close();
}
double Client::getFreq() {
return getFloat("f");
}
int Client::setFreq(double freq) {
return setFloat("F", freq);
}
// TODO: get/setMode
// TODO: get/setVFO
double Client::getRIT() {
return getFloat("j");
}
int Client::setRIT(double rit) {
return setFloat("J", rit);
}
double Client::getXIT() {
return getFloat("z");
}
int Client::setXIT(double rit) {
return setFloat("Z", rit);
}
int Client::getPTT() {
return getInt("t");
}
int Client::setPTT(bool ptt) {
return setInt("T", ptt);
}
// TODO: get/setSplitVFO
double Client::getSplitFreq() {
return getFloat("i");
}
int Client::setSplitFreq(double splitFreq) {
return setFloat("I", splitFreq);
}
// TODO: get/setSplitMode
int Client::getAntenna() {
return getInt("y");
}
int Client::setAntenna(int ant) {
return setInt("Y", ant);
}
// TODO: sendMorse
int Client::getDCD() {
return getInt("\x8B");
}
// TODO: get/setRepeaterShift
double Client::getRepeaterOffset() {
return getFloat("o");
}
int Client::setRepeaterOffset(double offset) {
return setFloat("O", offset);
}
double Client::getCTCSSTone() {
return (double)getInt("c") / 10.0;
}
int Client::setCTCSSTone(double tone) {
return setInt("C", (int)round(tone * 10.0));
}
// TODO: get/setDCSCode
double Client::getCTCSSSquelch() {
return getFloat("\x91");
}
int Client::setCTCSSSquelch(double squelch) {
return setFloat("\x90", squelch);
}
// TODO: get/setDCSSquelch
double Client::getTuningStep() {
return getFloat("n");
}
int Client::setTuningStep(double step) {
return setFloat("N", step);
}
// TODO: A bunch of other shit
int Client::setBank(int bank) {
return setInt("B", bank);
}
int Client::getMem() {
return getInt("e");
}
int Client::setMem(int mem) {
return setInt("E", mem);
}
int recvLine(std::shared_ptr<net::Socket> sock, std::vector<std::string>& args) {
// Read line
std::string line = "";
int err = sock->recvline(line, 0, 1000);
if (err <= 0) { return err; }
// Split
for (int i = 0; i < line.size(); i++) {
// Skip spaces
for (; line[i] == ' '; i++);
if (i == line.size()) { break; }
// Read part
std::string part = "";
for (; i < line.size() && line[i] != ' '; i++) { part += line[i]; }
args.push_back(part);
}
return args.size();
}
int Client::recvStatus() {
// Read line
std::vector<std::string> args;
int err = recvLine(sock, args);
if (err != 2) { return -1; }
// Check format
if (args[0] != "RPRT") { return -1; }
// Decode status
return std::stoi(args[1]);
}
int Client::getInt(std::string cmd) {
// Send command
sock->sendstr(cmd + "\n");
// Read line
std::vector<std::string> args;
int err = recvLine(sock, args);
if (err != 1) { return -1; }
// Decode frequency
return std::stoi(args[0]);
}
int Client::setInt(std::string cmd, int value) {
// Send command
char buf[128];
sprintf(buf, "%s %d\n", cmd.c_str(), value);
sock->sendstr(buf);
// Receive status
return recvStatus();
}
double Client::getFloat(std::string cmd) {
// Send command
sock->sendstr(cmd + "\n");
// Read line
std::vector<std::string> args;
int err = recvLine(sock, args);
if (err != 1) { return -1; }
// Decode frequency
return std::stod(args[0]);
}
int Client::setFloat(std::string cmd, double value) {
// Send command
char buf[128];
sprintf(buf, "%s %lf\n", cmd.c_str(), value);
sock->sendstr(buf);
// Receive status
return recvStatus();
}
std::string Client::getString(std::string cmd) {
// TODO
return "";
}
int Client::setString(std::string cmd, std::string value) {
// TODO
return -1;
}
std::shared_ptr<Client> connect(std::string host, int port) {
return std::make_shared<Client>(net::connect(host, port));
}
Server::Server(std::shared_ptr<net::Listener> listener) {
this->listener = listener;
listenThread = std::thread(&Server::listenWorker, this);
}
Server::~Server() {
stop();
}
bool Server::listening() {
return listener->listening();
}
void Server::stop() {
// Stop listen worker
listener->stop();
if (listenThread.joinable()) { listenThread.join(); }
// Stop individual client threads
while (true) {
// Check how many sockets are left and stop if they're all closed
}
}
void Server::listenWorker() {
while (true) {
// Wait for new client
auto sock = listener->accept();
if (!sock) { break; }
// Add socket to list
{
std::lock_guard<std::mutex> lck(socketsMtx);
sockets.push_back(sock);
}
// Start handler thread
std::thread acceptThread(&Server::acceptWorker, this);
acceptThread.detach();
}
}
void Server::acceptWorker(std::shared_ptr<Socket> sock) {
while (true) {
// Receive command
std::vector<std::string> args;
int argCount = recvLine(sock, args);
if (argCount <= 0) { break; }
// Parse command
std::string cmd = args[0];
if (cmd == "f" || cmd == "\\get_freq") {
// TODO: Check if handler exists
double freq = 0;
int res = getFreqHandler(freq);
if (!res) {
sendFloat(sock, freq);
}
else {
sendStatus(sock, res);
}
}
if (cmd == "F" || cmd == "\\set_freq") {
}
else {
// Return error
sendStatus(sock, -1);
}
}
}
void Server::sendStatus(std::shared_ptr<Socket> sock, int status) {
char buf[128];
sprintf(buf, "RPRT %d\n", status);
sock->sendstr(buf);
}
void sendInt(std::shared_ptr<Socket> sock, int value) {
char buf[128];
sprintf(buf, "%d\n", value);
sock->sendstr(buf);
}
void sendFloat(std::shared_ptr<Socket> sock, double value) {
char buf[128];
sprintf(buf, "%lf\n", value);
sock->sendstr(buf);
}
}

View File

@ -0,0 +1,326 @@
#pragma once
#include "../net.h"
#include <vector>
#include <string>
#include <functional>
#include <thread>
namespace net::rigctl {
enum Mode {
MODE_INVALID = -1,
MODE_USB,
MODE_LSB,
MODE_CW,
MODE_CWR,
MODE_RTTY,
MODE_RTTYR,
MODE_AM,
MODE_FM,
MODE_WFM,
MODE_AMS,
MODE_PKTLSB,
MODE_PKTUSB,
MODE_PKTFM,
MODE_ECSSUSB,
MODE_ECSSLSB,
MODE_FA,
MODE_SAM,
MODE_SAL,
MODE_SAH,
MODE_DSB
};
enum VFO {
VFO_INVALID = -1,
VFO_VFOA,
VFO_VFOB,
VFO_VFOC,
VFO_CURR_VFO,
VFO_VFO,
VFO_MEM,
VFO_MAIN,
VFO_SUB,
VFO_TX,
VFO_RX
};
enum RepeaterShift {
REPEATER_SHIFT_INVALID = -1,
REPEATER_SHIFT_NONE,
REPEATER_SHIFT_PLUS,
REPEATER_SHIFT_MINUS
};
enum Function {
FUNCTION_INVALID = -1,
FUNCTION_FAGC,
FUNCTION_NB,
FUNCTION_COMP,
FUNCTION_VOX,
FUNCTION_TONE,
FUNCTION_TSQL,
FUNCTION_SBKIN,
FUNCTION_FBKIN,
FUNCTION_ANF,
FUNCTION_NR,
FUNCTION_AIP,
FUNCTION_APF,
FUNCTION_MON,
FUNCTION_MN,
FUNCTION_RF,
FUNCTION_ARO,
FUNCTION_LOCK,
FUNCTION_MUTE,
FUNCTION_VSC,
FUNCTION_REV,
FUNCTION_SQL,
FUNCTION_ABM,
FUNCTION_BC,
FUNCTION_MBC,
FUNCTION_RIT,
FUNCTION_AFC,
FUNCTION_SATMODE,
FUNCTION_SCOPE,
FUNCTION_RESUME,
FUNCTION_TBURST,
FUNCTION_TUNER,
FUNCTION_XIT
};
enum Level {
LEVEL_INVALID = -1,
LEVEL_PREAMP,
LEVEL_ATT,
LEVEL_VOX,
LEVEL_AF,
LEVEL_RF,
LEVEL_SQL,
LEVEL_IF,
LEVEL_APF,
LEVEL_NR,
LEVEL_PBT_IN,
LEVEL_PBT_OUT,
LEVEL_CWPITCH,
LEVEL_RFPOWER,
LEVEL_RFPOWER_METER,
LEVEL_RFPOWER_METER_WATTS,
LEVEL_MICGAIN,
LEVEL_KEYSPD,
LEVEL_NOTCHF,
LEVEL_COMP,
LEVEL_AGC,
LEVEL_BKINDL,
LEVEL_BAL,
LEVEL_METER,
LEVEL_VOXGAIN,
LEVEL_ANTIVOX,
LEVEL_SLOPE_LOW,
LEVEL_SLOPE_HIGH,
LEVEL_RAWSTR,
LEVEL_SWR,
LEVEL_ALC,
LEVEL_STRENGTH
};
enum Param {
PARAM_INVALID = -1,
PARAM_ANN,
PARAM_APO,
PARAM_BACKLIGHT,
PARAM_BEEP,
PARAM_TIME,
PARAM_BAT,
PARAM_KEYLIGHT
};
enum VFOMemOp {
VFO_MEM_OP_INVALID = -1,
VFO_MEM_OP_CPY,
VFO_MEM_OP_XCHG,
VFO_MEM_OP_FROM_VFO,
VFO_MEM_OP_TO_VFO,
VFO_MEM_OP_MCL,
VFO_MEM_OP_UP,
VFO_MEM_OP_DOWN,
VFO_MEM_OP_BAND_UP,
VFO_MEM_OP_BAND_DOWN,
VFO_MEM_OP_LEFT,
VFO_MEM_OP_RIGHT,
VFO_MEM_OP_TUNE,
VFO_MEM_OP_TOGGLE
};
enum ScanFunc {
SCAN_FUNC_INVALID = -1,
SCAN_FUNC_STOP,
SCAN_FUNC_MEM,
SCAN_FUNC_SLCT,
SCAN_FUNC_PRIO,
SCAN_FUNC_PROG,
SCAN_FUNC_DELTA,
SCAN_FUNC_VFO,
SCAN_FUNC_PLT
};
enum TranceiveMode {
TRANCEIVE_MODE_INVALID = -1,
TRANCEIVE_MODE_OFF,
TRANCEIVE_MODE_RIG,
TRANCEIVE_MODE_POLL
};
enum ResetType {
RESET_TYPE_INVALID = -1,
RESET_TYPE_SOFT_RESET = (1 << 0),
RESET_TYPE_VFO_RESET = (1 << 1),
RESET_TYPE_MEM_CLEAR_RESET = (1 << 2),
RESET_TYPE_MASTER_RESET = (1 << 3)
};
class Client {
public:
Client(std::shared_ptr<Socket> sock);
~Client();
bool isOpen();
void close();
double getFreq();
int setFreq(double freq);
Mode getMode();
int setMode(Mode mode);
VFO getVFO();
int setVFO(VFO vfo);
double getRIT();
int setRIT(double rit);
double getXIT();
int setXIT(double rit);
int getPTT();
int setPTT(bool ptt);
// TODO: get/setSplitVFO
double getSplitFreq();
int setSplitFreq(double splitFreq);
// TODO: get/setSplitMode
int getAntenna();
int setAntenna(int ant);
// TODO: sendMorse
int getDCD();
RepeaterShift getRepeaterShift();
int setRepeaterShift(RepeaterShift shift);
double getRepeaterOffset();
int setRepeaterOffset(double offset);
double getCTCSSTone();
int setCTCSSTone(double tone);
// TODO: get/setDCSCode
double getCTCSSSquelch();
int setCTCSSSquelch(double squelch);
// TODO: get/setDCSSquelch
double getTuningStep();
int setTuningStep(double step);
std::vector<Function> getSupportedFunctions();
int getFunction(Function func);
int setFunction(Function func, bool enabled);
std::vector<Level> getSupportedLevels();
double getLevel(Level level);
int setLevel(Level level, double value);
std::vector<Param> getSupportedParams();
double getParam(Param param);
int setParam(Param param, double value);
int setBank(int bank);
int getMem();
int setMem(int mem);
int vfoOp(VFOMemOp op);
int scan(ScanFunc func);
// TODO: get/setChannel
TranceiveMode getTranceiveMode();
int setTranceiveMode(TranceiveMode mode);
int reset(ResetType type);
private:
int recvStatus();
int getInt(std::string cmd);
int setInt(std::string cmd, int value);
double getFloat(std::string cmd);
int setFloat(std::string cmd, double value);
std::string getString(std::string cmd);
int setString(std::string cmd, std::string value);
std::shared_ptr<Socket> sock;
};
class Server {
public:
Server(std::shared_ptr<net::Listener> listener);
~Server();
bool listening();
void stop();
template<typename Func>
void onGetFreq(Func func) {
getFreqHandler = func;
}
template<typename Func, typename T>
void onGetFreq(Func func, T* ctx) {
getFreqHandler = std::bind(func, ctx, std::placeholders::_1);
}
template<typename Func>
void onSetFreq(Func func) {
setFreqHandler = func;
}
template<typename Func, typename T>
void onSetFreq(Func func, T* ctx) {
setFreqHandler = std::bind(func, ctx, std::placeholders::_1);
}
private:
void listenWorker();
void acceptWorker(std::shared_ptr<Socket> sock);
void sendStatus(std::shared_ptr<Socket> sock, int status);
void sendInt(std::shared_ptr<Socket> sock, int value);
void sendFloat(std::shared_ptr<Socket> sock, double value);
std::function<int(double&)> getFreqHandler = NULL;
std::function<int(double)> setFreqHandler = NULL;
std::thread listenThread;
std::shared_ptr<net::Listener> listener;
std::mutex socketsMtx;
std::vector<std::shared_ptr<net::Socket>> sockets;
};
std::shared_ptr<Client> connect(std::string host, int port = 4532);
std::shared_ptr<Server> listen(std::string host, int port = 4532);
}

View File

@ -1,4 +1,4 @@
#include <utils/networking.h>
#include <utils/proto/rigctl.h>
#include <imgui.h>
#include <module.h>
#include <gui/gui.h>
@ -22,16 +22,11 @@ SDRPP_MOD_INFO{
/* Max instances */ 1
};
enum {
RECORDER_TYPE_RECORDER,
RECORDER_TYPE_METEOR_DEMODULATOR
};
ConfigManager config;
class SigctlServerModule : public ModuleManager::Instance {
class RigctlClientModule : public ModuleManager::Instance {
public:
SigctlServerModule(std::string name) {
RigctlClientModule(std::string name) {
this->name = name;
strcpy(host, "127.0.0.1");
@ -42,7 +37,7 @@ public:
gui::menu.registerEntry(name, menuHandler, this, NULL);
}
~SigctlServerModule() {
~RigctlClientModule() {
stop();
gui::menu.removeEntry(name);
}
@ -84,7 +79,7 @@ public:
private:
static void menuHandler(void* ctx) {
SigctlServerModule* _this = (SigctlServerModule*)ctx;
RigctlClientModule* _this = (RigctlClientModule*)ctx;
float menuWidth = ImGui::GetContentRegionAvail().x;
if (_this->running) { style::beginDisabled(); }
@ -123,7 +118,11 @@ private:
}
static void retuneHandler(double freq, void* ctx) {
spdlog::warn("PAN RETUNE: {0}", freq);
RigctlClientModule* _this = (RigctlClientModule*)ctx;
if (!_this->client || !_this->client->isOpen()) { return; }
//spdlog::warn("PAN RETUNE: {0}", freq);
_this->client->setFreq(freq);
}
std::string name;
@ -133,6 +132,7 @@ private:
char host[1024];
int port = 4532;
std::shared_ptr<net::rigctl::Client> client;
double ifFreq = 8830000.0;
@ -146,11 +146,11 @@ MOD_EXPORT void _INIT_() {
}
MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) {
return new SigctlServerModule(name);
return new RigctlClientModule(name);
}
MOD_EXPORT void _DELETE_INSTANCE_(void* instance) {
delete (SigctlServerModule*)instance;
delete (RigctlClientModule*)instance;
}
MOD_EXPORT void _END_() {