diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-03-14 13:24:12 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-03-14 13:24:12 +0100 |
commit | a1c36919884e76c67c19896c526b139d84b8478c (patch) | |
tree | ab59345868766e0a0eb36b6bdfb123a6329abec7 | |
parent | 33fab4f1008c1af305e6426233a1a87bd683782d (diff) | |
download | dabmod-a1c36919884e76c67c19896c526b139d84b8478c.tar.gz dabmod-a1c36919884e76c67c19896c526b139d84b8478c.tar.bz2 dabmod-a1c36919884e76c67c19896c526b139d84b8478c.zip |
Update RemoteControl from dabmux
-rw-r--r-- | src/DabMod.cpp | 9 | ||||
-rw-r--r-- | src/FIRFilter.cpp | 4 | ||||
-rw-r--r-- | src/FIRFilter.h | 4 | ||||
-rw-r--r-- | src/OutputUHD.cpp | 4 | ||||
-rw-r--r-- | src/OutputUHD.h | 4 | ||||
-rw-r--r-- | src/RemoteControl.cpp | 86 | ||||
-rw-r--r-- | src/RemoteControl.h | 87 |
7 files changed, 130 insertions, 68 deletions
diff --git a/src/DabMod.cpp b/src/DabMod.cpp index 7a147a0..bd83531 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -327,7 +327,6 @@ int main(int argc, char* argv[]) try { int telnetport = pt.get<int>("remotecontrol.telnetport"); RemoteControllerTelnet* telnetrc = new RemoteControllerTelnet(telnetport); - telnetrc->start(); rc = telnetrc; } catch (std::exception &e) { @@ -686,6 +685,14 @@ int main(int argc, char* argv[]) // Proccessing data //////////////////////////////////////////////////////////////// flowgraph->run(); + + /* Check every once in a while if the remote control + * is still working */ + if (rc && (frame % 250) == 0 && rc->fault_detected()) { + fprintf(stderr, + "Detected Remote Control fault, restarting it\n"); + rc->restart(); + } } if (framesize == 0) { fprintf(stderr, "End of file reached.\n"); diff --git a/src/FIRFilter.cpp b/src/FIRFilter.cpp index 0bcd5e9..f9ad31d 100644 --- a/src/FIRFilter.cpp +++ b/src/FIRFilter.cpp @@ -414,7 +414,7 @@ int FIRFilter::process(Buffer* const dataIn, Buffer* dataOut) } -void FIRFilter::set_parameter(string parameter, string value) +void FIRFilter::set_parameter(const string& parameter, const string& value) { stringstream ss(value); ss.exceptions ( stringstream::failbit | stringstream::badbit ); @@ -438,7 +438,7 @@ void FIRFilter::set_parameter(string parameter, string value) } } -string FIRFilter::get_parameter(string parameter) +const string FIRFilter::get_parameter(const string& parameter) const { stringstream ss; if (parameter == "ntaps") { diff --git a/src/FIRFilter.h b/src/FIRFilter.h index 8707dac..59e954d 100644 --- a/src/FIRFilter.h +++ b/src/FIRFilter.h @@ -108,8 +108,8 @@ public: const char* name() { return "FIRFilter"; } /******* REMOTE CONTROL ********/ - void set_parameter(string parameter, string value); - string get_parameter(string parameter); + virtual void set_parameter(const string& parameter, const string& value); + virtual const string get_parameter(const string& parameter) const; protected: diff --git a/src/OutputUHD.cpp b/src/OutputUHD.cpp index 5e66fb3..b8d421f 100644 --- a/src/OutputUHD.cpp +++ b/src/OutputUHD.cpp @@ -543,7 +543,7 @@ loopend: } -void OutputUHD::set_parameter(string parameter, string value) +void OutputUHD::set_parameter(const string& parameter, const string& value) { stringstream ss(value); ss.exceptions ( stringstream::failbit | stringstream::badbit ); @@ -571,7 +571,7 @@ void OutputUHD::set_parameter(string parameter, string value) } } -string OutputUHD::get_parameter(string parameter) +const string OutputUHD::get_parameter(const string& parameter) const { stringstream ss; if (parameter == "txgain") { diff --git a/src/OutputUHD.h b/src/OutputUHD.h index 29f54d6..e30f897 100644 --- a/src/OutputUHD.h +++ b/src/OutputUHD.h @@ -190,10 +190,10 @@ class OutputUHD: public ModOutput, public RemoteControllable { */ /* Base function to set parameters. */ - virtual void set_parameter(string parameter, string value); + virtual void set_parameter(const string& parameter, const string& value); /* Getting a parameter always returns a string. */ - virtual string get_parameter(string parameter); + virtual const string get_parameter(const string& parameter) const; protected: diff --git a/src/RemoteControl.cpp b/src/RemoteControl.cpp index f0318a2..03cef2c 100644 --- a/src/RemoteControl.cpp +++ b/src/RemoteControl.cpp @@ -3,7 +3,8 @@ Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Written by Matthias P. Braendli, matthias.braendli@mpb.li, 2012 + Copyright (C) 2014 + Matthias P. Braendli, matthias.braendli@mpb.li */ /* This file is part of ODR-DabMod. @@ -26,13 +27,35 @@ #include <iostream> #include <string> #include <boost/asio.hpp> +#include <boost/thread.hpp> #include "RemoteControl.h" using boost::asio::ip::tcp; -void -RemoteControllerTelnet::process(long) + +void RemoteControllerTelnet::restart() +{ + m_restarter_thread = boost::thread(&RemoteControllerTelnet::restart_thread, + this, 0); +} + +// This runs in a separate thread, because +// it would take too long to be done in the main loop +// thread. +void RemoteControllerTelnet::restart_thread(long) +{ + m_running = false; + + if (m_port) { + m_child_thread.interrupt(); + m_child_thread.join(); + } + + m_child_thread = boost::thread(&RemoteControllerTelnet::process, this, 0); +} + +void RemoteControllerTelnet::process(long) { m_welcome = "ODR-DabMod Remote Control CLI\nWrite 'help' for help.\n**********\n"; m_prompt = "> "; @@ -71,7 +94,7 @@ RemoteControllerTelnet::process(long) std::getline(str, in_message); if (length == 0) { - std::cerr << "Connection terminated" << std::endl; + std::cerr << "RC: Connection terminated" << std::endl; break; } @@ -85,22 +108,22 @@ RemoteControllerTelnet::process(long) continue; } - std::cerr << "Got message '" << in_message << "'" << std::endl; + std::cerr << "RC: Got message '" << in_message << "'" << std::endl; dispatch_command(socket, in_message); } - std::cerr << "Closing socket" << std::endl; + std::cerr << "RC: Closing socket" << std::endl; socket.close(); } } catch (std::exception& e) { - std::cerr << e.what() << std::endl; + std::cerr << "Remote control caught exception: " << e.what() << std::endl; + m_fault = true; } } -void -RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string command) +void RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string command) { vector<string> cmd = tokenise_(command); @@ -108,9 +131,7 @@ RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string command) reply(socket, "The following commands are supported:\n" " list\n" - " * Lists the modules that are loaded\n" - " list MODULE\n" - " * Lists the parameters exported by module MODULE\n" + " * Lists the modules that are loaded and their parameters\n" " show MODULE\n" " * Lists all parameters and their values from module MODULE\n" " get MODULE PARAMETER\n" @@ -127,22 +148,15 @@ RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string command) if (cmd.size() == 1) { for (list<RemoteControllable*>::iterator it = m_cohort.begin(); it != m_cohort.end(); ++it) { - ss << (*it)->get_rc_name() << " "; - } - } - else if (cmd.size() == 2) { - try { - stringstream ss; - - list< vector<string> > params = get_parameter_descriptions_(cmd[1]); - for (list< vector<string> >::iterator it = params.begin(); - it != params.end(); ++it) { - ss << (*it)[0] << " : " << (*it)[1] << endl; + ss << (*it)->get_rc_name() << endl; + + list< vector<string> >::iterator param; + list< vector<string> > params = (*it)->get_parameter_descriptions(); + for (param = params.begin(); + param != params.end(); + ++param) { + ss << "\t" << (*param)[0] << " : " << (*param)[1] << endl; } - reply(socket, ss.str()); - } - catch (ParameterError &e) { - reply(socket, e.what()); } } else { @@ -188,9 +202,18 @@ RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string command) } } else if (cmd[0] == "set") { - if (cmd.size() == 4) { + if (cmd.size() >= 4) { try { - set_param_(cmd[1], cmd[2], cmd[3]); + stringstream new_param_value; + for (int i = 3; i < cmd.size(); i++) { + new_param_value << cmd[i]; + + if (i+1 < cmd.size()) { + new_param_value << " "; + } + } + + set_param_(cmd[1], cmd[2], new_param_value.str()); reply(socket, "ok"); } catch (ParameterError &e) { @@ -202,7 +225,7 @@ RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string command) } else { - reply(socket, "Incorrect parameters for command 'get'"); + reply(socket, "Incorrect parameters for command 'set'"); } } else if (cmd[0] == "quit") { @@ -213,8 +236,7 @@ RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string command) } } -void -RemoteControllerTelnet::reply(tcp::socket& socket, string message) +void RemoteControllerTelnet::reply(tcp::socket& socket, string message) { boost::system::error_code ignored_error; stringstream ss; diff --git a/src/RemoteControl.h b/src/RemoteControl.h index 0881797..dd31fc2 100644 --- a/src/RemoteControl.h +++ b/src/RemoteControl.h @@ -67,11 +67,23 @@ class ParameterError : public std::exception class RemoteControllable; -/* Remote controllers (that recieve orders from the user) must implement BaseRemoteController */ +/* Remote controllers (that recieve orders from the user) + * must implement BaseRemoteController + */ class BaseRemoteController { public: /* Add a new controllable under this controller's command */ virtual void enrol(RemoteControllable* controllable) = 0; + + /* When this returns one, the remote controller cannot be + * used anymore, and must be restarted by dabmux + */ + virtual bool fault_detected() = 0; + + /* In case of a fault, the remote controller can be + * restarted. + */ + virtual void restart() = 0; }; /* Objects that support remote control must implement the following class */ @@ -84,7 +96,7 @@ class RemoteControllable { * It might be used in the commands the user has to type, so keep * it short */ - virtual std::string get_rc_name() { return m_name; } + virtual std::string get_rc_name() const { return m_name; } /* Tell the controllable to enrol at the given controller */ virtual void enrol_at(BaseRemoteController& controller) { @@ -92,10 +104,9 @@ class RemoteControllable { } /* Return a list of possible parameters that can be set */ - virtual list<string> get_supported_parameters() { - cerr << "get_sup_par" << m_parameters.size() << endl; + virtual list<string> get_supported_parameters() const { list<string> parameterlist; - for (list< vector<string> >::iterator it = m_parameters.begin(); + for (list< vector<string> >::const_iterator it = m_parameters.begin(); it != m_parameters.end(); ++it) { parameterlist.push_back((*it)[0]); } @@ -103,15 +114,17 @@ class RemoteControllable { } /* Return a mapping of the descriptions of all parameters */ - virtual std::list< std::vector<std::string> > get_parameter_descriptions() { + virtual std::list< std::vector<std::string> > + get_parameter_descriptions() const { return m_parameters; } /* Base function to set parameters. */ - virtual void set_parameter(string parameter, string value) = 0; + virtual void set_parameter(const string& parameter, + const string& value) = 0; /* Getting a parameter always returns a string. */ - virtual string get_parameter(string parameter) = 0; + virtual const string get_parameter(const string& parameter) const = 0; protected: std::string m_name; @@ -123,34 +136,45 @@ class RemoteControllable { */ class RemoteControllerTelnet : public BaseRemoteController { public: - RemoteControllerTelnet(int port) { - m_port = port; - m_running = false; - }; + RemoteControllerTelnet() + : m_running(false), m_fault(false), + m_port(0) { } - void start() { - m_running = true; - m_child_thread = boost::thread(&RemoteControllerTelnet::process, this, 0); - } + RemoteControllerTelnet(int port) + : m_running(true), m_fault(false), + m_child_thread(&RemoteControllerTelnet::process, this, 0), + m_port(port) + { } - void stop() { + ~RemoteControllerTelnet() { m_running = false; - m_child_thread.interrupt(); - m_child_thread.join(); + m_fault = false; + if (m_port) { + m_child_thread.interrupt(); + m_child_thread.join(); + } + } + + void enrol(RemoteControllable* controllable) { + m_cohort.push_back(controllable); } + virtual bool fault_detected() { return m_fault; }; + + virtual void restart(); + + private: + void restart_thread(long); + void process(long); void dispatch_command(tcp::socket& socket, string command); void reply(tcp::socket& socket, string message); - void enrol(RemoteControllable* controllable) { - m_cohort.push_back(controllable); - } - + RemoteControllerTelnet& operator=(const RemoteControllerTelnet& other); + RemoteControllerTelnet(const RemoteControllerTelnet& other); - private: vector<string> tokenise_(string message) { vector<string> all_tokens; @@ -188,8 +212,8 @@ class RemoteControllerTelnet : public BaseRemoteController { list< vector<string> > allparams; list<string> params = controllable->get_supported_parameters(); - cerr << "# of supported parameters " << params.size() << endl; - for (list<string>::iterator it = params.begin(); it != params.end(); ++it) { + for (list<string>::iterator it = params.begin(); + it != params.end(); ++it) { vector<string> item; item.push_back(*it); item.push_back(controllable->get_parameter(*it)); @@ -210,6 +234,11 @@ class RemoteControllerTelnet : public BaseRemoteController { } bool m_running; + + /* This is set to true if a fault occurred */ + bool m_fault; + boost::thread m_restarter_thread; + boost::thread m_child_thread; /* This controller commands the controllables in the cohort */ @@ -222,11 +251,15 @@ class RemoteControllerTelnet : public BaseRemoteController { }; -/* The Dummy remote controller does nothing +/* The Dummy remote controller does nothing, and never fails */ class RemoteControllerDummy : public BaseRemoteController { public: void enrol(RemoteControllable* controllable) {}; + + bool fault_detected() { return false; }; + + virtual void restart() {}; }; #endif |