PiScan/src/server/connection/DebugConsole.cpp

256 lines
9.0 KiB
C++

/*
* DebugConsole.cpp
*
* Created on: Jul 5, 2020
* Author: ezra
*/
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include "PiScan.h"
#include "DebugServer.h"
#include "loguru.hpp"
#include "threadname.h"
#include "connection/DebugConsole.h"
#include "constants.h"
namespace piscan {
namespace server {
namespace connection {
#define DS_THREAD_NAME "DebugConsole"
using namespace piscan;
using piscan::app::BasicReturnTuple;
bool DebugConsole::connect(){
Connection::connect();
std::cerr << "\nConnecting...\n";
_run = true;
_requestThread = std::thread(&DebugConsole::_consoleInputFunc, this);
return true;
}
void DebugConsole::disconnect(){
Connection::disconnect();
_run = false;
std::fprintf(stdin, "\n");
std::cerr << "\nConsole disconnected\n";
notifyDisconnected();
}
void DebugConsole::_consoleInputFunc() {
setThreadName(DS_THREAD_NAME);
std::string input = "";
std::vector<std::string> tokens(5);
std::stringstream sstream;
std::string intermediate;
std::cerr << "\nConsole connected\n";
std::map<app::ReturnStatus, std::string> friendlyReturnCodes;
friendlyReturnCodes[app::SUCCESS] = "Success";
friendlyReturnCodes[app::INVALID] = "Invalid parameters";
friendlyReturnCodes[app::NOT_IMPLEMENTED] = "Function not yet implemented";
std::map<std::string, std::function<piscan::app::BasicReturnTuple()>> apiMap;
apiMap["scanlist"] = []() { return app::data::getScanList(); };
apiMap["systems"] = []() { return app::data::getSystemList(); };
apiMap["systemat"] = [tokens]() { return app::data::getSystemByIndex(std::stoi(tokens[1])); };
apiMap["entrylist"] = [tokens]() { return app::data::getEntryList(std::stoi(tokens[1])); };
apiMap["entryat"] = [tokens]() { return app::data::getEntryByIndex(std::stoi(tokens[1]), std::stoi(tokens[2])); };
apiMap["createsystem"] = [tokens]() { return app::data::system::create(/*TODO*/); };
apiMap["replacesystem"] = [tokens]() { return app::data::system::replace(std::stoi(tokens[1])/*, TODO*/); };
apiMap["removesystem"] = [tokens]() { return app::data::system::remove(std::stoi(tokens[1])); };
apiMap["locksystem"] = [tokens]() { return app::data::system::setLockout(std::stoi(tokens[1]), std::stoi(tokens[2])); };
apiMap["setsystemindex"] = [tokens]() { return app::data::system::setIndex(std::stoi(tokens[1]), std::stoi(tokens[2])); };
apiMap["createentry"] = [tokens]() { return app::data::system::entry::create(std::stoi(tokens[1])/*,TODO*/); };
apiMap["replaceentry"] = [tokens]() { return app::data::system::entry::replace(std::stoi(tokens[1]), std::stoi(tokens[2])/*, TODO*/); };
apiMap["removeentry"] = [tokens]() { return app::data::system::entry::remove(std::stoi(tokens[1]), std::stoi(tokens[2])); };
apiMap["lockentry"] = [tokens]() { return app::data::system::entry::setLockout(std::stoi(tokens[1]), std::stoi(tokens[2]), std::stoi(tokens[3])); };
apiMap["setentryindex"] = [tokens]() { return app::data::system::entry::setIndex(std::stoi(tokens[1]), std::stoi(tokens[2]), std::stoi(tokens[3])); };
apiMap["config"] = []() { return app::configuration::getFullConfig(); };
apiMap["setconfig"] = [tokens]() { return app::configuration::setConfig(); };
apiMap["generalcfg"] = []() { return app::configuration::getGeneralConfig(); };
apiMap["setgeneralcfg"] = [tokens]() { return app::configuration::setGeneralConfig(); };
apiMap["demodcfg"] = []() { return app::configuration::getDemodConfig(); };
apiMap["setdemodcfg"] = [tokens]() { return app::configuration::setDemodConfig(); };
apiMap["rtspcfg"] = []() { return app::configuration::getAudioServerConfig(); };
apiMap["setrtspcfg"] = [tokens]() { return app::configuration::setAudioServerConfig(); };
apiMap["tunerlist"] = []() { return app::configuration::getTunerList(); };
getSystemInfo();
getScannerContext();
getDemodContext();
while(_run){
input.clear();
std::getline(std::cin, input);
LOG_F(7, "Command entered: %s", input.c_str());
sstream = std::stringstream(input);
while(std::getline(sstream, intermediate, ' '))
tokens.push_back(intermediate);
try {
if (!tokens[0].compare("exit")) {
_run = false;
//systemFunction(SystemFunction::STOP);
app::system::stopSystem();
}
else if (!tokens[0].compare("verbosity")){
loguru::g_stderr_verbosity = std::stoi(tokens[1]);
std::cerr << "Verbosity set to " << loguru::g_stderr_verbosity << std::endl;
}
else if (!tokens[0].compare("squelch")) {
if (tokens.size() > 1) {
int level = std::stoi(tokens[1]);
setDemodSquelch(level);
}
else
getDemodContext();
} else if (!tokens[0].compare("scan"))
scanStart();
else if (!tokens[0].compare("hold")) {
if (tokens.size() > 2) {
std::vector<int> entryIndex;
for(size_t i = 1; i < tokens.size(); i++)
entryIndex.push_back(std::stoi(tokens[i]));
scanHoldEntry(entryIndex);
}
else
scanHold();
} else if (!tokens[0].compare("gain")) {
if (tokens.size() > 1) {
int gain = 0;
if (!tokens[1].compare("auto"))
gain = AUTO_GAIN;
else
gain = std::stoi(tokens[1]);
setDemodGain(gain);
}
else
getDemodContext();
} else if (!tokens[0].compare("manual")) {
if(tokens.size() > 2)
scanManualEntry(std::stof(tokens[1]), tokens[2]);
else
scanManualEntry(std::stof(tokens[1]));
}
else if (!tokens[0].compare("get")){
if(!tokens[1].compare("context"))
getScannerContext();
}
else if (!tokens[0].compare("help")) {
std::cerr << "\n Available commands:"
<< "\n\thelp\t\tPrints all commands"
<< "\n\texit\t\tExit program"
<< "\n\tverbosity [0-9]\tSet console logging verbosity"
<< "\n\tsquelch [level]\tSet squelch threshold"
<< "\n\tgain [level]\tSet tuner gain - use \"auto\" for AGC"
<< "\n\tscan\t\tContinue scanning entries"
<< "\n\thold\t\tHold scanner at current entry"
<< "\n\tmanual [freq]\tTune to the specified frequency"
<< "\n\tget [subcommand]"
<< "\n\t\tcontext\t\tReturns scanner status"
<< "\n";
for (auto cmd = apiMap.begin(); cmd != apiMap.end(); cmd++) {
std::cerr << "\t" << cmd->first << "\n";
}
} else
try {
auto ret = apiMap[tokens[0]]();
std::cerr << "Status: " << friendlyReturnCodes[std::get<0>(ret)] << "\n";
} catch (std::exception& e) {
std::cerr << "Invalid command\n";
}
} catch (std::exception& e) {
std::cerr << "Argument missing or typo in the command\n";
}
sstream.clear();
tokens.clear();
}
std::cerr << "\nConsole thread exited\n";
}
void DebugConsole::contextUpdate(piscan::server::context::ScannerContext context){
/*std::thread([context]{*/
switch(context.state){
case piscan::server::context::ScannerContext::SCAN:
std::cerr << "\rScanning..." << std::endl;
break;
case piscan::server::context::ScannerContext::HOLD:
std::cerr << "\rHold: " << context.entryIndex << " | "
<< context.systemTag << " | "
<< context.entryTag << " | " << (context.frequency / 1E6) << "MHz | "
<< "LO: " << context.lockout << "\n";
break;
case piscan::server::context::ScannerContext::RECEIVE:
std::cerr << "\rReceive: " << context.entryIndex << " | "
<< context.systemTag << " | "
<< context.entryTag << " | " << (context.frequency / 1E6) << "MHz | "
<< "LO: " << context.lockout << "\n";
break;
default:
break;
}
/*});*/
}
void DebugConsole::handleSystemMessage(piscan::server::context::GeneralMessage message){
static std::map<piscan::server::context::GeneralMessage::MessageType, std::string> messageLabels = {
{piscan::server::context::GeneralMessage::INFO, "info"},
{piscan::server::context::GeneralMessage::ERROR, "error"},
{piscan::server::context::GeneralMessage::WARNING, "warning"}
};
std::cerr << messageLabels[message.type];
/*std::thread([message]{*/
/*std::cerr << "\rSystem message: ";
switch(message.type){
case piscan::server::context::GeneralMessage::INFO:
std::cerr << "info";
break;
case piscan::server::context::GeneralMessage::WARNING:
std::cerr << "warning";
break;
case piscan::server::context::GeneralMessage::ERROR:
std::cerr << "error";
break;
}*/
std::cerr << "\n" << message.content;
/*});*/
}
void DebugConsole::contextUpdate(piscan::server::context::DemodContext context) {
std::cerr << "\rGain: ";
/*if(context.gain >= 0)
std::cerr << context.gain;
else
std::cerr << "auto";*/
std::cerr << ((context.gain >= 0) ? std::to_string(context.gain) : "auto");
std::cerr << "\nSquelch: " << context.squelch << std::endl;
}
void DebugConsole::handleSystemInfo(const piscan::server::context::SystemInfo info){
std::cerr << "System version: " << info.version << "\n";
std::cerr << "Build number: " << info.buildNumber << "\n";
std::cerr << "Squelch range: [" << info.squelchRange.first << ", " << info.squelchRange.second << "\n";
std::cerr << "Modulatons:\n";
for(auto mod = info.supportedModulations.begin(); mod != info.supportedModulations.end(); mod++){
std::cerr << "\t" << *mod << "\n";
}
}
void DebugConsole::handleSignalLevel(const int level){
std::cerr << "\r" << "Signal: " << level << "\t\t\t\t";
}
}
}
}