/*
Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
Her Majesty the Queen in Right of Canada (Communications Research
Center Canada)
Written by Matthias P. Braendli, matthias.braendli@mpb.li, 2012
*/
/*
This file is part of CRC-DADMOD.
CRC-DADMOD is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
CRC-DADMOD is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CRC-DADMOD. If not, see .
*/
#ifndef _REMOTECONTROL_H
#define _REMOTECONTROL_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using boost::asio::ip::tcp;
class ParameterError : public std::exception
{
public:
ParameterError(string message) : message_(message) {}
~ParameterError() throw() {};
const char* what() { return message_.c_str(); }
private:
string message_;
};
class RemoteControllable;
/* 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;
};
/* Objects that support remote control must implement the following class */
class RemoteControllable {
public:
/* return a short name used to identify the controllable.
* It might be used in the commands the user has to type, so keep
* it short
*/
virtual std::string get_rc_name() = 0;
/* Tell the controllable to enrol at the given controller */
virtual void enrol_at(BaseRemoteController& controller) {
controller.enrol(this);
}
/* Return a list of possible parameters that can be set */
virtual list get_supported_parameters() = 0;
/* Base function to set parameters. */
virtual void set_parameter(string parameter, string value) = 0;
/* Convenience functions for other common types */
virtual void set_parameter(string parameter, double value) = 0;
virtual void set_parameter(string parameter, long value) = 0;
/* Getting a parameter always returns a string. */
virtual string get_parameter(string parameter) = 0;
};
/* Implements a Remote controller based on a simple telnet CLI
* that listens on localhost
*/
class RemoteControllerTelnet : public BaseRemoteController {
public:
RemoteControllerTelnet(int port) {
port_ = port;
running_ = false;
};
void start() {
running_ = true;
child_thread_ = boost::thread(&RemoteControllerTelnet::process, this, 0);
}
void stop() {
running_ = false;
child_thread_.interrupt();
child_thread_.join();
}
void process(long);
void dispatch_command(tcp::socket& socket, string command);
void reply(tcp::socket& socket, string message);
void enrol(RemoteControllable* controllable) {
cohort_.push_back(controllable);
}
private:
vector tokenise_(string message) {
vector all_tokens;
boost::char_separator sep(" ");
boost::tokenizer< boost::char_separator > tokens(message, sep);
BOOST_FOREACH (const string& t, tokens) {
all_tokens.push_back(t);
}
return all_tokens;
}
list get_param_list_(string controllable) {
for (list::iterator it = cohort_.begin(); it != cohort_.end(); it++) {
if ((*it)->get_rc_name() == controllable)
{
return (*it)->get_supported_parameters();
}
}
throw ParameterError("Module name unknown");
}
list< vector > get_param_list_values_(string controllable) {
list< vector > allparams;
for (list::iterator it = cohort_.begin(); it != cohort_.end(); it++) {
if ((*it)->get_rc_name() == controllable)
{
list params = (*it)->get_supported_parameters();
for (list::iterator it2 = params.begin(); it2 != params.end(); it2++) {
vector item;
item.push_back(*it2);
item.push_back((*it)->get_parameter(*it2));
allparams.push_back(item);
}
return allparams;
}
}
throw ParameterError("Module name unknown");
}
string get_param_(string controllable, string param) {
for (list::iterator it = cohort_.begin(); it != cohort_.end(); it++) {
if ((*it)->get_rc_name() == controllable)
{
return (*it)->get_parameter(param);
}
}
throw ParameterError("Module name unknown");
}
void set_param_(string controllable, string param, string value) {
for (list::iterator it = cohort_.begin(); it != cohort_.end(); it++) {
if ((*it)->get_rc_name() == controllable)
{
(*it)->set_parameter(param, value);
return;
}
}
throw ParameterError("Module name unknown");
}
bool running_;
boost::thread child_thread_;
/* This controller commands the controllables in the cohort */
list cohort_;
std::string welcome_;
std::string prompt_;
int port_;
};
#endif