#ifndef FACT_DimState #define FACT_DimState #include "State.h" class DimState { protected: typedef function callback; callback fCallback; public: DimState(const string &n, const string s="STATE") : server(n), service(n+"/"+s), info(make_pair(Time(), -4)) { } virtual ~DimState() { } string server; string service; pair info; string msg; virtual void Subscribe(StateMachineImp &imp) { imp.Subscribe(service.c_str()) (imp.Wrap(bind(&DimState::Handler, this, placeholders::_1))); } void SetCallback(const callback &cb) { fCallback = cb; } virtual void Handler(const EventImp &evt) { const bool disconnected = evt.GetSize()==0; info = make_pair(evt.GetTime(), disconnected ? -4 : evt.GetQoS()); msg = disconnected ? "" : evt.GetString(); if (fCallback) fCallback(evt); } const Time &time() const { return info.first; } const int &state() const { return info.second; } bool online() const { return info.second>-4; } virtual State description() const { return State(-5, ""); } }; ostream &operator<<(ostream& out, const DimState &s) { const State rc = s.description(); out << s.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - "; out << kBold << s.server; if (s.state()==-4) return out << ": Offline"; if (rc.index==-5) return out; out << ": "; if (rc.index==-2) out << s.state(); else out << rc.name << "[" << rc.index << "]"; if (!rc.comment.empty()) out << " - " << kBlue << rc.comment; return out; } class DimDescribedState : public DimState { vector states; public: DimDescribedState(const string &n) : DimState(n) { } virtual void Subscribe(StateMachineImp &imp) { imp.Subscribe((server+"/STATE_LIST").c_str()) (imp.Wrap(bind(&DimDescribedState::HandleDesc, this, placeholders::_1))); DimState::Subscribe(imp); } void HandleDesc(const EventImp &evt) { if (evt.GetSize()>0) { states = State::SplitStates(evt.GetString()); states.push_back(State(-4, "Offline")); } } State description() const { for (auto it=states.begin(); it!=states.end(); it++) if (it->index==state()) return *it; return State(-5, "n/a"); } }; class DimVersion : public DimState { public: DimVersion() : DimState("DIS_DNS", "VERSION_NUMBER") { } void Handler(const EventImp &evt) { DimState::Handler(evt); info.second = evt.GetSize()==4 ? evt.GetInt() : -4; } string version() const { if (info.second==0) return "Offline"; ostringstream out; out << "V" << info.second/100 << 'r' << info.second%100; return out.str(); } State description() const { return State(state(), version()); } }; class DimControl : public DimState { map fCallbacks; public: DimControl() : DimState("DIM_CONTROL") { } string file; string shortmsg; void AddCallback(const string &script, const callback &cb) { fCallbacks[script] = cb; } void Handler(const EventImp &evt) { DimState::Handler(evt); shortmsg = msg; file = ""; // Evaluate msg const size_t p0 = msg.find_first_of(':'); if (p0==string::npos) return; const size_t p1 = msg.find_last_of('['); if (p1==string::npos) return; const size_t p2 = msg.find_first_of(':', p0+1); const size_t p3 = p2==string::npos || p2>p1 ? p1-1 : p2; file = msg.substr(p0+2, p3-p0-2); shortmsg.erase(p0, p3-p0); const auto func = fCallbacks.find(file); if (func==fCallbacks.end()) return; // Call callback func->second(evt); } State description() const { return State(state(), "Current label"); } }; #endif