From 208851ebc5f91f3ae04e2fb9d65486ebf2f0bfff Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Tue, 7 Feb 2023 12:04:29 +0100 Subject: [PATCH] cleanup --- core/src/utils/proto/rigctl.cpp | 318 +++++++++++++++++++++++ core/src/utils/proto/rigctl.h | 326 ++++++++++++++++++++++++ misc_modules/rigctl_client/src/main.cpp | 26 +- 3 files changed, 657 insertions(+), 13 deletions(-) create mode 100644 core/src/utils/proto/rigctl.cpp create mode 100644 core/src/utils/proto/rigctl.h diff --git a/core/src/utils/proto/rigctl.cpp b/core/src/utils/proto/rigctl.cpp new file mode 100644 index 00000000..b9393aaa --- /dev/null +++ b/core/src/utils/proto/rigctl.cpp @@ -0,0 +1,318 @@ +#include "rigctl.h" + +namespace net::rigctl { + Client::Client(std::shared_ptr 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 sock, std::vector& 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 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 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 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 connect(std::string host, int port) { + return std::make_shared(net::connect(host, port)); + } + + Server::Server(std::shared_ptr 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 lck(socketsMtx); + sockets.push_back(sock); + } + + // Start handler thread + std::thread acceptThread(&Server::acceptWorker, this); + acceptThread.detach(); + } + } + + void Server::acceptWorker(std::shared_ptr sock) { + while (true) { + // Receive command + std::vector 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 sock, int status) { + char buf[128]; + sprintf(buf, "RPRT %d\n", status); + sock->sendstr(buf); + } + + void sendInt(std::shared_ptr sock, int value) { + char buf[128]; + sprintf(buf, "%d\n", value); + sock->sendstr(buf); + } + + void sendFloat(std::shared_ptr sock, double value) { + char buf[128]; + sprintf(buf, "%lf\n", value); + sock->sendstr(buf); + } +} \ No newline at end of file diff --git a/core/src/utils/proto/rigctl.h b/core/src/utils/proto/rigctl.h new file mode 100644 index 00000000..93939cb9 --- /dev/null +++ b/core/src/utils/proto/rigctl.h @@ -0,0 +1,326 @@ +#pragma once +#include "../net.h" +#include +#include +#include +#include + +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 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 getSupportedFunctions(); + int getFunction(Function func); + int setFunction(Function func, bool enabled); + + std::vector getSupportedLevels(); + double getLevel(Level level); + int setLevel(Level level, double value); + + std::vector 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 sock; + + }; + + class Server { + public: + Server(std::shared_ptr listener); + ~Server(); + + bool listening(); + void stop(); + + template + void onGetFreq(Func func) { + getFreqHandler = func; + } + template + void onGetFreq(Func func, T* ctx) { + getFreqHandler = std::bind(func, ctx, std::placeholders::_1); + } + + template + void onSetFreq(Func func) { + setFreqHandler = func; + } + template + void onSetFreq(Func func, T* ctx) { + setFreqHandler = std::bind(func, ctx, std::placeholders::_1); + } + + private: + void listenWorker(); + void acceptWorker(std::shared_ptr sock); + void sendStatus(std::shared_ptr sock, int status); + void sendInt(std::shared_ptr sock, int value); + void sendFloat(std::shared_ptr sock, double value); + + std::function getFreqHandler = NULL; + std::function setFreqHandler = NULL; + + std::thread listenThread; + std::shared_ptr listener; + + std::mutex socketsMtx; + std::vector> sockets; + }; + + std::shared_ptr connect(std::string host, int port = 4532); + std::shared_ptr listen(std::string host, int port = 4532); +} \ No newline at end of file diff --git a/misc_modules/rigctl_client/src/main.cpp b/misc_modules/rigctl_client/src/main.cpp index 3cd7c32a..01cc837a 100644 --- a/misc_modules/rigctl_client/src/main.cpp +++ b/misc_modules/rigctl_client/src/main.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -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 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_() {