Changeset 18717 for branches/FACT++_lidctrl_usb
- Timestamp:
- 01/06/17 14:42:41 (8 years ago)
- Location:
- branches/FACT++_lidctrl_usb/src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/FACT++_lidctrl_usb/src/HeadersLid.h
r18125 r18717 2 2 #define FACT_HeadersLid 3 3 4 namespace Lid 4 namespace LidCtrlUsb 5 5 { 6 6 namespace State … … 8 8 enum states_t 9 9 { 10 kDisconnected = 1, 11 kConnected, 12 kUnidentified, 13 kInconsistent, 14 kUnknown, 15 kPowerProblem, 16 kOvercurrent, 10 kOpen = 1, 17 11 kClosed, 18 kOpen,19 kMoving,20 kLocked21 12 }; 22 }; 23 }; 13 } 14 } 15 24 16 #endif -
branches/FACT++_lidctrl_usb/src/lidctrl.cc
r18125 r18717 1 #include <boost/array.hpp> 2 3 #include <string> // std::string 4 #include <algorithm> // std::transform 5 #include <cctype> // std::tolower 6 7 #include <QtXml/QDomDocument> 8 9 #include "FACT.h" 1 #include <functional> 2 3 #include <boost/bind.hpp> 4 10 5 #include "Dim.h" 11 6 #include "Event.h" 7 #include "Shell.h" 12 8 #include "StateMachineDim.h" 13 9 #include "StateMachineAsio.h" 14 #include "Connection.h" 15 #include "LocalControl.h" 10 #include "ConnectionUSB.h" 16 11 #include "Configuration.h" 17 12 #include "Console.h" … … 19 14 #include "tools.h" 20 15 16 #include "LocalControl.h" 21 17 #include "HeadersLid.h" 22 18 23 namespace ba = boost::asio;24 namespace bs = boost::system;19 namespace ba = boost::asio; 20 namespace bs = boost::system; 25 21 namespace dummy = ba::placeholders; 26 22 23 using namespace std::placeholders; 27 24 using namespace std; 28 25 29 class ConnectionLid : public Connection 30 { 31 protected: 32 33 struct Lid 34 { 35 int id; 36 37 float position; 38 float current; 39 string status; 40 41 Lid(int i) : id(i) { } 42 43 bool Set(const QDomNamedNodeMap &map) 44 { 45 if (!map.contains("id") || !map.contains("value")) 46 return false; 47 48 QString item = map.namedItem("id").nodeValue(); 49 QString value = map.namedItem("value").nodeValue(); 50 51 const char c = '0'+id; 52 53 if (item==(QString("cur")+c)) 54 { 55 current = value.toFloat(); 56 return true; 57 } 58 59 if (item==(QString("pos")+c)) 60 { 61 position = value.toFloat(); 62 return true; 63 } 64 65 if (item==(QString("lid")+c)) 66 { 67 status = value.toStdString(); 68 return true; 69 } 70 71 return false; 72 } 73 74 void Print(ostream &out) 75 { 76 out << "Lid" << id << " @ " << position << " / " << current << "A [" << status << "]" << endl; 77 } 78 79 }; 80 26 using namespace LidCtrlUsb; 27 28 #include "DimDescriptionService.h" 29 30 class ConnectionLid : public ConnectionUSB 31 { 32 vector<uint8_t> fRecievedBytes; 33 DimDescribedService fDimLid; 81 34 private: 82 uint16_t fInterval; 83 84 bool fIsVerbose; 85 86 string fSite; 87 string fRdfData; 88 89 boost::array<char, 4096> fArray; 90 91 string fNextCommand; 92 93 Time fLastReport; 94 95 Lid fLid1; 96 Lid fLid2; 97 98 virtual void Update(const Lid &, const Lid &) 99 { 100 } 101 102 103 void ProcessAnswer() 104 { 105 if (fIsVerbose) 106 { 107 Out() << "------------------------------------------------------" << endl; 108 Out() << fRdfData << endl; 109 Out() << "------------------------------------------------------" << endl; 110 } 111 112 fRdfData.insert(0, "<?xml version=\"1.0\"?>\n"); 113 114 QDomDocument doc; 115 if (!doc.setContent(QString(fRdfData.c_str()), false)) 116 { 117 Warn("Parsing of html failed."); 118 return; 119 } 120 121 if (fIsVerbose) 122 { 123 Out() << "Parsed:\n-------\n" << doc.toString().toStdString() << endl; 124 Out() << "------------------------------------------------------" << endl; 125 } 126 127 const QDomNodeList imageElems = doc.elementsByTagName("span"); // "input" 128 129 /* 130 // elementById 131 for (unsigned int i=0; i<imageElems.length(); i++) 132 { 133 QDomElement e = imageElems.item(i).toElement(); 134 Out() << "<" << e.tagName().toStdString() << " "; 135 136 QDomNamedNodeMap att = e.attributes(); 137 138 for (int j=0; j<att.size(); j++) 139 { 140 Out() << att.item(j).nodeName().toStdString() << "="; 141 Out() << att.item(j).nodeValue().toStdString() << " "; 142 } 143 Out() << "> " << e.text().toStdString() << endl; 144 }*/ 145 146 for (unsigned int i=0; i<imageElems.length(); i++) 147 { 148 const QDomElement e = imageElems.item(i).toElement(); 149 150 const QDomNamedNodeMap att = e.attributes(); 151 152 fLid1.Set(att); 153 fLid2.Set(att); 154 } 155 156 if (fIsVerbose) 157 { 158 fLid1.Print(Out()); 159 fLid2.Print(Out()); 160 Out() << "------------------------------------------------------" << endl; 161 } 162 163 Update(fLid1, fLid2); 164 165 fRdfData = ""; 166 167 if ((fLid1.status!="Open" && fLid1.status!="Closed" && fLid1.status!="Power Problem" && fLid1.status!="Unknown" && fLid1.status!="Overcurrent") || 168 (fLid2.status!="Open" && fLid2.status!="Closed" && fLid2.status!="Power Problem" && fLid2.status!="Unknown" && fLid1.status!="Overcurrent")) 169 Warn("Lid reported status unknown by lidctrl ("+fLid1.status+"/"+fLid2.status+")"); 170 171 fLastReport = Time(); 172 } 173 174 void HandleRead(const boost::system::error_code& err, size_t bytes_received) 175 { 176 // Do not schedule a new read if the connection failed. 177 if (bytes_received==0 || err) 178 { 179 if (err==ba::error::eof) 180 { 181 //Warn("Connection closed by remote host."); 182 ProcessAnswer(); 183 PostClose(false); 184 return; 185 } 186 187 // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category)) 188 // 125: Operation canceled 189 if (err && err!=ba::error::eof && // Connection closed by remote host 190 err!=ba::error::basic_errors::not_connected && // Connection closed by remote host 191 err!=ba::error::basic_errors::operation_aborted) // Connection closed by us 192 { 193 ostringstream str; 194 str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl; 195 Error(str); 196 } 197 PostClose(err!=ba::error::basic_errors::operation_aborted); 198 199 fRdfData = ""; 200 return; 201 } 202 203 fRdfData += string(fArray.data(), bytes_received); 204 205 //cout << "." << flush; 206 207 // Does the message contain a header? 208 const size_t p1 = fRdfData.find("\r\n\r\n"); 209 if (p1!=string::npos) 210 { 211 // Does the answer also contain the body? 212 const size_t p2 = fRdfData.find("\r\n\r\n", p1+4); 213 if (p2!=string::npos) 214 { 215 ProcessAnswer(); 216 } 217 } 218 219 // Go on reading until the web-server closes the connection 220 StartReadReport(); 221 } 222 223 boost::asio::streambuf fBuffer; 224 225 void StartReadReport() 226 { 227 async_read_some(ba::buffer(fArray), 228 boost::bind(&ConnectionLid::HandleRead, this, 229 dummy::error, dummy::bytes_transferred)); 230 } 231 232 boost::asio::deadline_timer fKeepAlive; 233 234 void PostRequest(string cmd, const string &args="") 235 { 236 cmd += " "+fSite+" HTTP/1.1\r\n" 237 //"Connection: Keep-Alive\r\n" 238 ; 239 240 ostringstream msg; 241 msg << args.length(); 242 243 cmd += "Content-Length: "; 244 cmd += msg.str(); 245 cmd +="\r\n"; 246 247 if (args.length()>0) 248 cmd += "\r\n"+args + "\r\n"; 249 250 cmd += "\r\n"; 251 252 //cout << "Post: " << cmd << endl; 253 PostMessage(cmd); 254 } 255 256 void HandleRequest(const bs::error_code &error) 257 { 258 // 125: Operation canceled (bs::error_code(125, bs::system_category)) 259 if (error && error!=ba::error::basic_errors::operation_aborted) 260 { 261 ostringstream str; 262 str << "Write timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl; 263 Error(str); 264 265 PostClose(false); 266 return; 267 } 268 269 if (!is_open()) 270 { 271 // For example: Here we could schedule a new accept if we 272 // would not want to allow two connections at the same time. 273 PostClose(true); 274 return; 275 } 276 277 // Check whether the deadline has passed. We compare the deadline 278 // against the current time since a new asynchronous operation 279 // may have moved the deadline before this actor had a chance 280 // to run. 281 if (fKeepAlive.expires_at() > ba::deadline_timer::traits_type::now()) 282 return; 283 284 Request(); 285 } 286 287 288 private: 35 36 37 void HandleReceivedData(const boost::system::error_code&, size_t bytes_received, int type, int counter) 38 { 39 Out() << fRecievedBytes; 40 AsyncRead(ba::buffer(fRecievedBytes, 100), 0, 0); 41 42 } 43 44 289 45 // This is called when a connection was established 290 46 void ConnectionEstablished() 291 47 { 292 Request(); 293 StartReadReport(); 294 } 295 296 void ConnectionFailed() 297 { 298 StartConnect(); 299 } 48 AsyncRead(ba::buffer(fRecievedBytes, 100), 0, 0); 49 } 50 300 51 301 52 public: 302 static const uint16_t kMaxAddr; 303 304 public: 305 ConnectionLid(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()), 306 fIsVerbose(true), fLastReport(Time::none), 307 fLid1(1), fLid2(2), fKeepAlive(ioservice) 53 ConnectionLid(ba::io_service& ioservice, MessageImp &imp) : 54 ConnectionUSB(ioservice, imp()), 55 fRecievedBytes(1024), 56 fDimLid("LID_CTRL_USB/STUFF", "S:1","|Stuff[foo]:some text.") 308 57 { 309 58 SetLogStream(&imp); 310 59 } 311 60 312 void SetVerbose(bool b) 313 { 314 fIsVerbose = b; 315 Connection::SetVerbose(b); 316 } 317 318 void SetInterval(uint16_t i) 319 { 320 fInterval = i; 321 } 322 323 void SetSite(const string &site) 324 { 325 fSite = site; 326 } 327 328 void Post(const string &post) 329 { 330 fNextCommand = post; 331 332 fLid1.status = ""; 333 fLid2.status = ""; 334 //PostRequest("POST", post); 335 } 336 337 void Request() 338 { 339 PostRequest("POST", fNextCommand); 340 fNextCommand = ""; 341 342 fKeepAlive.expires_from_now(boost::posix_time::seconds(fInterval)); 343 fKeepAlive.async_wait(boost::bind(&ConnectionLid::HandleRequest, 344 this, dummy::error)); 345 } 346 347 int GetInterval() const 348 { 349 return fInterval; 350 } 351 352 int GetState() const 353 { 354 using namespace Lid; 355 356 // Timeout 357 if (fLastReport.IsValid() && fLastReport+boost::posix_time::seconds(fInterval*2)<Time()) 358 return State::kDisconnected; 359 360 // Unidentified state detected 361 if ((!fLid1.status.empty() && fLid1.status!="Open" && fLid1.status!="Closed" && fLid1.status!="Power Problem" && fLid1.status!="Unknown" && fLid1.status!="Overcurrent") || 362 (!fLid2.status.empty() && fLid2.status!="Open" && fLid2.status!="Closed" && fLid2.status!="Power Problem" && fLid2.status!="Unknown" && fLid2.status!="Overcurrent")) 363 return State::kUnidentified; 364 365 // This is an assumption, but the best we have... 366 if (fLid1.status=="Closed" && fLid2.status=="Power Problem") 367 return State::kClosed; 368 if (fLid2.status=="Closed" && fLid1.status=="Power Problem") 369 return State::kClosed; 370 if (fLid1.status=="Open" && fLid2.status=="Power Problem") 371 return State::kOpen; 372 if (fLid2.status=="Open" && fLid1.status=="Power Problem") 373 return State::kOpen; 374 375 // Inconsistency 376 if (fLid1.status!=fLid2.status) 377 return State::kInconsistent; 378 379 // Unknown 380 if (fLid1.status=="Unknown") 381 return State::kUnknown; 382 383 // Power Problem 384 if (fLid1.status=="Power Problem") 385 return State::kPowerProblem; 386 387 // Overcurrent 388 if (fLid1.status=="Overcurrent") 389 return State::kOvercurrent; 390 391 // Closed 392 if (fLid1.status=="Closed") 393 return State::kClosed; 394 395 // Open 396 if (fLid1.status=="Open") 397 return State::kOpen; 398 399 return State::kConnected; 61 State::states_t GetStatus() 62 { 63 return State::kOpen; 400 64 } 401 65 }; 402 66 403 const uint16_t ConnectionLid::kMaxAddr = 0xfff;404 405 67 // ------------------------------------------------------------------------ 406 68 407 #include "DimDescriptionService.h"408 409 class ConnectionDimWeather : public ConnectionLid410 {411 private:412 DimDescribedService fDim;413 414 public:415 ConnectionDimWeather(ba::io_service& ioservice, MessageImp &imp) :416 ConnectionLid(ioservice, imp),417 fDim("LID_CONTROL/DATA", "S:2;F:2;F:2",418 "|status[bool]:Lid1/2 open or closed"419 "|I[A]:Lid1/2 current"420 "|P[dac]:Lid1/2 hall sensor position in averaged dac counts")421 {422 }423 424 void Update(const Lid &l1, const Lid &l2)425 {426 struct DimData427 {428 int16_t status[2];429 float current[2];430 float position[2];431 432 DimData() { status[0] = status[1] = -1; }433 434 } __attribute__((__packed__));435 436 DimData data;437 438 if (l1.status=="Unknown")439 data.status[0] = 3;440 if (l1.status=="Power Problem")441 data.status[0] = 2;442 if (l1.status=="Open")443 data.status[0] = 1;444 if (l1.status=="Closed")445 data.status[0] = 0;446 447 if (l2.status=="Unknown")448 data.status[1] = 3;449 if (l2.status=="Power Problem")450 data.status[1] = 2;451 if (l2.status=="Open")452 data.status[1] = 1;453 if (l2.status=="Closed")454 data.status[1] = 0;455 456 data.current[0] = l1.current;457 data.current[1] = l2.current;458 459 data.position[0] = l1.position;460 data.position[1] = l2.position;461 462 fDim.setQuality(GetState());463 fDim.Update(data);464 }465 };466 467 // ------------------------------------------------------------------------468 469 69 template <class T, class S> 470 class StateMachineLidControl : public StateMachineAsio<T> 471 { 472 private: 473 S fLid; 474 Time fLastCommand; 475 Time fSunRise; 476 477 uint16_t fTimeToMove; 70 class StateMachineLid : public StateMachineAsio<T> 71 { 72 int Wrap(boost::function<void()> f) 73 { 74 f(); 75 return T::GetCurrentState(); 76 } 77 78 function<int(const EventImp &)> Wrapper(function<void()> func) 79 { 80 return bind(&StateMachineLid::Wrap, this, func); 81 } 478 82 479 83 bool CheckEventSize(size_t has, const char *name, size_t size) … … 488 92 } 489 93 490 int SetVerbosity(const EventImp &evt) 491 { 492 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1)) 493 return T::kSM_FatalError; 494 495 fLid.SetVerbose(evt.GetBool()); 496 94 private: 95 S fLid; 96 97 int Disconnect() 98 { 99 fLid.PostClose(-1); 497 100 return T::GetCurrentState(); 498 101 } 499 102 500 int Post(const EventImp &evt) 501 { 502 fLid.Post(evt.GetText()); 103 int Reconnect(const EventImp &evt) 104 { 105 fLid.PostClose(-1); 106 ba::io_service::poll(); 107 fLid.PostClose(0); 503 108 return T::GetCurrentState(); 504 109 } 505 110 506 int Open() 507 { 508 fLastCommand = Time(); 509 fLid.Post("Button5="); 510 return Lid::State::kMoving; 511 } 512 int Close() 513 { 514 fLastCommand = Time(); 515 fLid.Post("Button6="); 516 return Lid::State::kMoving; 517 518 } 519 /* 520 int MoveMotor(const EventImp &evt, int mid) 521 { 522 if (!CheckEventSize(evt.GetSize(), "MoveMotor", 2)) 523 return T::kSM_FatalError; 524 525 if (evt.GetUShort()>0xfff) 111 int Execute() 112 { 113 const int state = fLid.GetStatus(); 114 return state; 115 } 116 117 public: 118 StateMachineLid(ostream &out=cout) : 119 StateMachineAsio<T>(out, "LID_CTRL_USB"), fLid(*this, *this) 120 { 121 T::AddStateName(State::kOpen, "Open", "Lid is open"); 122 T::AddStateName(State::kClosed, "Closed", "Lid is closed"); 123 T::AddEvent("OPEN")(bind(&StateMachineLid::Open, this))("Open Lid"); 124 T::AddEvent("CLOSE")(bind(&StateMachineLid::Close, this))("Close Lid"); 125 } 126 127 ~StateMachineLid() 128 { 129 } 130 131 int EvalOptions(Configuration &conf) 132 { 133 if (conf.Has("dev")) 526 134 { 527 ostringstream msg; 528 msg << "Position " << evt.GetUShort() << " for motor " << mid+1 << " out of range [0,1023]."; 529 T::Error(msg); 530 return T::GetCurrentState(); 135 fLid.SetEndpoint(conf.Get<string>("dev")); 136 T::Message("Setting device to "+fLid.URL()); 137 fLid.Connect(); 531 138 } 532 533 fLid.MoveMotor(mid, evt.GetUShort());534 535 return T::GetCurrentState();536 }*/537 538 int Unlock()539 {540 return fLid.GetState();541 }542 543 int Execute()544 {545 const int rc = fLid.GetState();546 const int state = T::GetCurrentState();547 548 if (state==Lid::State::kMoving &&549 (rc==Lid::State::kConnected || rc==Lid::State::kDisconnected) &&550 fLastCommand+boost::posix_time::seconds(fTimeToMove+fLid.GetInterval()) > Time())551 {552 return Lid::State::kMoving;553 }554 555 const Time now;556 if (now>fSunRise)557 {558 if (state!=Lid::State::kClosed && state!=Lid::State::kLocked && state>Lid::State::kDisconnected)559 {560 T::Error("Lidctrl not in 'Closed' at end of nautical twilight!");561 Close();562 }563 564 fSunRise = now.GetNextSunRise(-6);565 566 ostringstream msg;567 msg << "During next sun-rise nautical twilight will end at " << fSunRise;568 T::Info(msg);569 570 return Lid::State::kLocked;571 }572 573 return rc==Lid::State::kConnected ? state : rc;574 }575 576 577 public:578 StateMachineLidControl(ostream &out=cout) :579 StateMachineAsio<T>(out, "LID_CONTROL"), fLid(*this, *this),580 fSunRise(Time().GetNextSunRise(-6))581 {582 // State names583 T::AddStateName(Lid::State::kDisconnected, "NoConnection",584 "No connection to web-server could be established recently");585 586 T::AddStateName(Lid::State::kConnected, "Connected",587 "Connection established, but status still not known");588 589 T::AddStateName(Lid::State::kUnidentified, "Unidentified",590 "At least one lid reported a state which could not be identified by lidctrl");591 592 T::AddStateName(Lid::State::kInconsistent, "Inconsistent",593 "Both lids show different states");594 595 T::AddStateName(Lid::State::kUnknown, "Unknown",596 "Arduino reports at least one lids in an unknown status");597 598 T::AddStateName(Lid::State::kPowerProblem, "PowerProblem",599 "Arduino reports both lids to have a power problem (might also be that both are at the end switches)");600 601 T::AddStateName(Lid::State::kOvercurrent, "Overcurrent",602 "Arduino reports both lids to have a overcurrent (might also be that both are at the end switches)");603 604 T::AddStateName(Lid::State::kClosed, "Closed",605 "Both lids are closed");606 607 T::AddStateName(Lid::State::kOpen, "Open",608 "Both lids are open");609 610 T::AddStateName(Lid::State::kMoving, "Moving",611 "Lids are supposed to move, waiting for next status");612 613 T::AddStateName(Lid::State::kLocked, "Locked",614 "Locked, no commands accepted except UNLOCK.");615 616 617 // Verbosity commands618 T::AddEvent("SET_VERBOSE", "B")619 (bind(&StateMachineLidControl::SetVerbosity, this, placeholders::_1))620 ("set verbosity state"621 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");622 623 T::AddEvent("OPEN", Lid::State::kUnidentified, Lid::State::kInconsistent, Lid::State::kUnknown, Lid::State::kPowerProblem, Lid::State::kClosed)624 (bind(&StateMachineLidControl::Open, this))625 ("Open the lids");626 627 T::AddEvent("CLOSE")(Lid::State::kUnidentified)(Lid::State::kInconsistent)(Lid::State::kUnknown)(Lid::State::kOvercurrent)(Lid::State::kPowerProblem)(Lid::State::kOpen)628 (bind(&StateMachineLidControl::Close, this))629 ("Close the lids");630 631 T::AddEvent("POST", "C")(Lid::State::kUnidentified)(Lid::State::kInconsistent)(Lid::State::kUnknown)(Lid::State::kOvercurrent)(Lid::State::kPowerProblem)(Lid::State::kOpen)(Lid::State::kClosed)(Lid::State::kMoving)632 (bind(&StateMachineLidControl::Post, this, placeholders::_1))633 ("set verbosity state"634 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");635 636 T::AddEvent("UNLOCK", Lid::State::kLocked)637 (bind(&StateMachineLidControl::Unlock, this))638 ("Unlock if in locked state.");639 }640 641 int EvalOptions(Configuration &conf)642 {643 fLid.SetVerbose(!conf.Get<bool>("quiet"));644 fLid.SetInterval(conf.Get<uint16_t>("interval"));645 fLid.SetDebugTx(conf.Get<bool>("debug-tx"));646 fLid.SetSite(conf.Get<string>("url"));647 fLid.SetEndpoint(conf.Get<string>("addr"));648 fLid.StartConnect();649 650 fTimeToMove = conf.Get<uint16_t>("time-to-move");651 652 139 return -1; 653 140 } … … 657 144 658 145 #include "Main.h" 659 660 146 661 147 template<class T, class S, class R> 662 148 int RunShell(Configuration &conf) 663 149 { 664 return Main::execute<T, StateMachineLid Control<S, R>>(conf);150 return Main::execute<T, StateMachineLid<S, R>>(conf); 665 151 } 666 152 667 153 void SetupConfiguration(Configuration &conf) 668 154 { 669 po::options_description control("Lid control ");155 po::options_description control("Lid control options"); 670 156 control.add_options() 671 ("no-dim,d", po_switch(), "Disable dim services") 672 ("addr,a", var<string>(""), "Network address of the lid controling Arduino including port") 673 ("url,u", var<string>(""), "File name and path to load") 674 ("quiet,q", po_bool(true), "Disable printing contents of all received messages (except dynamic data) in clear text.") 675 ("interval,i", var<uint16_t>(5), "Interval between two updates on the server in seconds") 676 ("time-to-move", var<uint16_t>(20), "Expected minimum time the lid taks to open/close") 677 ("debug-tx", po_bool(), "Enable debugging of ethernet transmission.") 157 ("no-dim,d", po_bool(), "Disable dim services") 158 ("dev", var<string>(), "Device address of USB port to lid-arduino") 159 ("quiet,q", po_bool(true), "Disable printing contents of all received messages (except dynamic data) in clear text.") 678 160 ; 679 161 … … 681 163 } 682 164 683 /*684 Extract usage clause(s) [if any] for SYNOPSIS.685 Translators: "Usage" and "or" here are patterns (regular expressions) which686 are used to match the usage synopsis in program output. An example from cp687 (GNU coreutils) which contains both strings:688 Usage: cp [OPTION]... [-T] SOURCE DEST689 or: cp [OPTION]... SOURCE... DIRECTORY690 or: cp [OPTION]... -t DIRECTORY SOURCE...691 */692 165 void PrintUsage() 693 166 { 694 167 cout << 695 "The lidctrl is an interface to the LID control hardware.\n" 696 "\n" 697 "The default is that the program is started without user intercation. " 698 "All actions are supposed to arrive as DimCommands. Using the -c " 699 "option, a local shell can be initialized. With h or help a short " 700 "help message about the usuage can be brought to the screen.\n" 701 "\n" 702 "Usage: lidctrl [-c type] [OPTIONS]\n" 703 " or: lidctrl [OPTIONS]\n"; 168 "This lidctrl_usb program controls the Lid.\n" 169 "Usage: lidctrl_usb [-c type] [OPTIONS]\n" 170 " or: biaslidctrl_usbctrl [OPTIONS]\n"; 704 171 cout << endl; 705 172 } … … 707 174 void PrintHelp() 708 175 { 709 // Main::PrintHelp<StateMachineFTM<StateMachine, ConnectionFTM>>(); 710 711 /* Additional help text which is printed after the configuration 712 options goes here */ 713 714 /* 715 cout << "bla bla bla" << endl << endl; 716 cout << endl; 717 cout << "Environment:" << endl; 718 cout << "environment" << endl; 719 cout << endl; 720 cout << "Examples:" << endl; 721 cout << "test exam" << endl; 722 cout << endl; 723 cout << "Files:" << endl; 724 cout << "files" << endl; 725 cout << endl; 726 */ 176 Main::PrintHelp<StateMachineLid<StateMachine,ConnectionLid>>(); 727 177 } 728 178 … … 737 187 return 127; 738 188 739 // No console access at all 740 if (!conf.Has("console")) 741 { 742 if (conf.Get<bool>("no-dim")) 743 return RunShell<LocalStream, StateMachine, ConnectionLid>(conf); 189 { 190 // No console access at all 191 if (!conf.Has("console")) 192 { 193 return RunShell<LocalStream, StateMachineDim, ConnectionLid>(conf); 194 } 195 if (conf.Get<int>("console")==0) 196 return RunShell<LocalShell, StateMachineDim, ConnectionLid>(conf); 744 197 else 745 return RunShell<LocalStream, StateMachineDim, ConnectionDimWeather>(conf); 746 } 747 // Cosole access w/ and w/o Dim 748 if (conf.Get<bool>("no-dim")) 749 { 750 if (conf.Get<int>("console")==0) 751 return RunShell<LocalShell, StateMachine, ConnectionLid>(conf); 752 else 753 return RunShell<LocalConsole, StateMachine, ConnectionLid>(conf); 754 } 755 else 756 { 757 if (conf.Get<int>("console")==0) 758 return RunShell<LocalShell, StateMachineDim, ConnectionDimWeather>(conf); 759 else 760 return RunShell<LocalConsole, StateMachineDim, ConnectionDimWeather>(conf); 761 } 762 198 return RunShell<LocalConsole, StateMachineDim, ConnectionLid>(conf); 199 } 763 200 return 0; 764 201 }
Note:
See TracChangeset
for help on using the changeset viewer.