/* 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