Changeset 14128 for trunk/FACT++
- Timestamp:
- 06/08/12 18:06:52 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/dimctrl.cc
r14052 r14128 1 #ifndef FACT_DimCtrl 2 #define FACT_DimCtrl 3 4 #include "Main.h" 5 #include "tools.h" 6 #include "MessageDim.h" 1 #include "StateMachineDimControl.h" 7 2 #include "RemoteControl.h" 8 9 #include "InterpreterV8.h"10 3 11 4 using namespace std; 12 5 13 // ========================================================================6 // ------------------------------------------------------------------------ 14 7 8 #include "Main.h" 9 10 template<class T> 11 int RunShell(Configuration &conf) 12 { 13 StateMachineDimControl::fIsServer = conf.Get<bool>("server"); 14 return Main::execute<T, StateMachineDimControl>(conf); 15 } 16 17 void SetupConfiguration(Configuration &conf) 18 { 19 po::options_description control("Dim control options"); 20 control.add_options() 21 ("server", po_bool(false), "Start dimctrl as a dim server") 22 // ("verbosity,v", var<uint32_t>()->implicit_value(0), "Set a new verbosity level (see MessageImp)") 23 // ("quiet,q", po_bool(false), "Suppress all output except comments (log-level>=90)") 24 ("debug", po_bool(false), "Print the labels for debugging purpose") 25 ("start", var<string>(), "Start a java script with the given name") 26 ("batch", var<string>(), "Start a batch script with the given name at the given label (script.dim[:N])") 27 ("stop", po_switch(), "Stop a currently running script") 28 ("user,u", var<string>(""), "A user name - just for logging purposes (default is ${USER})") 29 ; 30 31 conf.AddEnv("user", "USER"); 32 33 conf.AddOptions(control); 34 } 15 35 16 36 /* … … 25 45 void PrintUsage() 26 46 { 27 cout << "\n" 28 "The console connects to all available Dim Servers and allows to " 29 "easily access all of their commands.\n" 47 cout << 48 "The feedback control the BIAS voltages based on the calibration signal.\n" 30 49 "\n" 31 "Usage: dimctrl [-c type] [OPTIONS]\n" 32 " or: dimctrl [OPTIONS]\n\n"; 50 "The default is that the program is started without user intercation. " 51 "All actions are supposed to arrive as DimCommands. Using the -c " 52 "option, a local shell can be initialized. With h or help a short " 53 "help message about the usuage can be brought to the screen.\n" 54 "\n" 55 "Usage: feedback [-c type] [OPTIONS]\n" 56 " or: feedback [OPTIONS]\n"; 33 57 cout << endl; 34 58 } … … 36 60 void PrintHelp() 37 61 { 38 Main::PrintUsage(); 62 Main::PrintHelp<StateMachineDimControl>(); 63 64 /* Additional help text which is printed after the configuration 65 options goes here */ 66 67 /* 68 cout << "bla bla bla" << endl << endl; 69 cout << endl; 70 cout << "Environment:" << endl; 71 cout << "environment" << endl; 72 cout << endl; 73 cout << "Examples:" << endl; 74 cout << "test exam" << endl; 75 cout << endl; 76 cout << "Files:" << endl; 77 cout << "files" << endl; 78 cout << endl; 79 */ 39 80 } 40 81 41 // A simple dummy state machine 42 class DimCtrl : public MainImp, public DimCommandHandler, public MessageDimTX 43 { 44 int fLabel; 45 int fStop; 46 int fVerbosity; 47 bool fDebug; 48 bool fIsServer; 49 string fUser; 50 51 DimDescribedService fSrvState; 52 DimCommand fDimStart; 53 DimCommand fDimStop; 54 55 map<string,string> fData; 56 string fScript; 57 string fScriptUser; 58 59 void ProcessStart() 60 { 61 if (!fScript.empty() || fLabel>-3) 62 { 63 Error("Script execution still in progress."); 64 return; 65 } 66 67 string opt(fDimStart.getString()); 68 69 fData = Tools::Split(opt); 70 71 if (opt.size()>0) 72 Debug("Start '"+opt+"' received."); 73 74 if (fDebug) 75 Debug("Received data: "+string(fDimStart.getString())); 76 77 if (opt.size()==0) 78 { 79 if (fData.size()==0) 80 Error("File name missing in DIM_CONTROL/START"); 81 else 82 Error("Equal sign missing in argument '"+fData.begin()->first+"'"); 83 84 return; 85 } 86 87 const auto user = fData.find("user"); 88 if (user!=fData.end()) 89 fScriptUser = user->second; 90 91 if (fDebug) 92 { 93 for (auto it=fData.begin(); it!=fData.end(); it++) 94 Debug(" Arg: "+it->first+" = "+it->second); 95 } 96 97 fScript = opt; 98 } 99 100 void StopScript() 101 { 102 Readline::StopScript(); 103 InterpreterV8::JsStop(); 104 } 105 106 void commandHandler() 107 { 108 if (getCommand()==&fDimStop) 109 { 110 const string user = fDimStop.getSize()>0 ? fDimStop.getString() : ""; 111 112 string msg = "Stop received"; 113 if (!user.empty()) 114 msg += " from user '"+user+"'"; 115 116 Debug(msg); 117 StopScript(); 118 } 119 120 if (getCommand()==&fDimStart) 121 ProcessStart(); 122 } 123 124 public: 125 DimCtrl(ostream &out=cout) : MessageDimTX("DIM_CONTROL", out), 126 fLabel(-3), fStop(-1), fVerbosity(0), fDebug(false), fIsServer(false), 127 fSrvState("DIM_CONTROL/STATE", "C", 128 "Provides the state of the state machine as quality of service." 129 "|Text[string]:A human readable string sent by the last state change."), 130 fDimStart("DIM_CONTROL/START", "C", this), 131 fDimStop("DIM_CONTROL/STOP", "C", this) 132 { 133 } 134 ~DimCtrl() 135 { 136 DimServer::stop(); 137 } 138 139 bool check(string &str) 140 { 141 for (auto c=str.begin(); c<str.end(); c++) 142 { 143 if ((*c>='A' && *c<='Z') || *c=='_') 144 continue; 145 146 if (*c++!=':') 147 return false; 148 149 if (c==str.end()) 150 return false; 151 152 if (*c!=' ') 153 return false; 154 155 str = string(c+1, str.end()); 156 return true; 157 } 158 159 return false; 160 } 161 162 string Line(const string &txt, char fill) 163 { 164 const int n = (55-txt.length())/2; 165 166 ostringstream out; 167 out << setfill(fill); 168 out << setw(n) << fill << ' '; 169 out << txt; 170 out << ' ' << setw(n) << fill; 171 172 if (2*n+txt.length()+2 != 57) 173 out << fill; 174 175 return out.str(); 176 } 177 178 int ChangeState(int qos, const Time &time=Time()) 179 { 180 ostringstream pid; 181 pid << getpid(); 182 183 fLabel = qos; 184 185 string msg; 186 switch (fLabel) 187 { 188 case -4: msg = "Boot"; break; 189 case -3: msg = "End"; break; 190 case -2: msg = "Load"; break; 191 case -1: msg = "Start"; break; 192 default: 193 { 194 ostringstream out; 195 out << "Label " << fLabel; 196 msg = out.str(); 197 } 198 } 199 200 if (fLabel<0) 201 msg += "-"+to_string(Readline::GetScriptDepth()); 202 203 msg += ": "+Readline::GetScript()+" ["; 204 if (!fScriptUser.empty()) 205 msg += fScriptUser+":"+pid.str(); 206 msg += "]"; 207 208 if (fDebug) 209 MessageDimTX::Write(time, Line(msg, fLabel<-1 ? '=' :'-'), 90); 210 211 fSrvState.setQuality(fLabel); 212 return fSrvState.Update(msg); 213 } 214 215 int Write(const Time &time, const std::string &txt, int qos=kMessage) 216 { 217 if (txt=="") 218 return ChangeState(qos, time); 219 220 if (qos<fVerbosity) 221 return 0; 222 223 // Avoid recursions 224 if (fIsServer && txt.substr(0, 13)=="DIM_CONTROL: ") 225 return 0; 226 227 // Don't send received messages via dim 228 string cpy(txt); 229 if (fIsServer && check(cpy)) 230 return MessageImp::Write(time, cpy, qos); 231 232 // Send all of our own messages via dim 233 return MessageDimTX::Write(time, txt, qos); 234 } 235 236 int EvalOptions(Configuration &conf) 237 { 238 fVerbosity = 90; 239 240 fUser = conf.Get<string>("user"); 241 fScriptUser = fUser; 242 243 if (conf.Get<bool>("stop")) 244 return Dim::SendCommand("DIM_CONTROL/STOP", fUser) + 1; 245 246 if (conf.Has("start")) 247 return Dim::SendCommand("DIM_CONTROL/START", conf.Get<string>("start")+" user="+fUser) + 1; 248 249 fVerbosity = 40; 250 251 if (conf.Has("verbosity")) 252 fVerbosity = conf.Get<uint32_t>("verbosity"); 253 254 if (conf.Get<bool>("quiet")) 255 fVerbosity = 90; 256 257 fIsServer = conf.Get<bool>("server"); 258 fDebug = conf.Get<bool>("debug"); 259 260 if (fIsServer) 261 { 262 // Sleep needed to ensure that the server can send 263 // an EXIT if another instance is already running 264 DimServer::start("DIM_CONTROL"); 265 //sleep(1); 266 ChangeState(-4); 267 } 268 269 return -1; 270 } 271 272 void Stop(int stop=0) { fStop = stop; StopScript(); } 273 int Run(bool) 274 { 275 while (fStop<0) 276 { 277 const string s = fScript; 278 if (!s.empty()) 279 { 280 Readline::Instance()->Execute(s, fData); 281 fScript = ""; 282 fScriptUser = fUser; 283 } 284 285 usleep(1000); 286 } 287 288 return fStop; 289 } 290 291 }; 292 293 void SetupConfiguration(Configuration &conf) 294 { 295 po::options_description control("Dim Control"); 296 control.add_options() 297 ("server", po_bool(false), "Start dimctrl as a dim server") 298 ("verbosity,v", var<uint32_t>()->implicit_value(0), "Set a new verbosity level (see MessageImp)") 299 ("quiet,q", po_bool(false), "Suppress all output except comments (log-level>=90)") 300 ("debug", po_bool(false), "Print the labels for debugging purpose") 301 ("start", var<string>(), "Start a script with the given name at the given label (script.dim[:N])") 302 ("stop", po_switch(), "Stop a currently running script") 303 ("user,u", var<string>(""), "A user name - just for logging purposes (default is ${USER})") 304 ; 305 306 conf.AddEnv("user", "USER"); 307 308 conf.AddOptions(control); 309 } 310 311 int main(int argc, const char *argv[]) 82 int main(int argc, const char* argv[]) 312 83 { 313 84 Configuration conf(argv[0]); … … 319 90 return 127; 320 91 92 //return RunShell<LocalStream>(conf); 93 321 94 if (!conf.Has("console")) 322 return Main::execute<RemoteStream, DimCtrl>(conf);95 return RunShell<RemoteStream>(conf); 323 96 324 97 if (conf.Get<int>("console")==0) 325 return Main::execute<RemoteShell, DimCtrl>(conf);98 return RunShell<RemoteShell>(conf); 326 99 else 327 return Main::execute<RemoteConsole, DimCtrl>(conf); 328 329 return 0; 100 return RunShell<RemoteConsole>(conf); 330 101 } 331 #endif
Note:
See TracChangeset
for help on using the changeset viewer.