aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2014-03-14 13:24:12 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2014-03-14 13:24:12 +0100
commita1c36919884e76c67c19896c526b139d84b8478c (patch)
treeab59345868766e0a0eb36b6bdfb123a6329abec7
parent33fab4f1008c1af305e6426233a1a87bd683782d (diff)
downloaddabmod-a1c36919884e76c67c19896c526b139d84b8478c.tar.gz
dabmod-a1c36919884e76c67c19896c526b139d84b8478c.tar.bz2
dabmod-a1c36919884e76c67c19896c526b139d84b8478c.zip
Update RemoteControl from dabmux
-rw-r--r--src/DabMod.cpp9
-rw-r--r--src/FIRFilter.cpp4
-rw-r--r--src/FIRFilter.h4
-rw-r--r--src/OutputUHD.cpp4
-rw-r--r--src/OutputUHD.h4
-rw-r--r--src/RemoteControl.cpp86
-rw-r--r--src/RemoteControl.h87
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