source: trunk/FACT++/src/DimState.h@ 14353

Last change on this file since 14353 was 14351, checked in by tbretz, 12 years ago
The state from the callback was not yet properly propagated. Implemented kSM_KeepState to signal that the state should not change.
File size: 10.3 KB
Line 
1#ifndef FACT_DimState
2#define FACT_DimState
3
4#include <set>
5#include <string>
6#include <functional>
7
8#include "State.h"
9#include "EventImp.h"
10#include "WindowLog.h"
11#include "Description.h"
12#include "StateMachineImp.h"
13
14class DimState
15{
16public:
17 enum
18 {
19 kOffline = -256,
20 kNotAvailable = -257,
21 };
22
23protected:
24 typedef std::function<int(const EventImp &)> callback;
25
26 callback fCallback;
27
28 void HandlerImp(const EventImp &evt)
29 {
30 const bool disconnected = evt.GetSize()==0;
31
32 last = cur;
33 cur = std::make_pair(evt.GetTime(), disconnected ? kOffline : evt.GetQoS());
34
35 msg = disconnected ? "" : evt.GetString();
36 }
37
38 int Callback(const EventImp &evt)
39 {
40 return fCallback ? fCallback(evt) : StateMachineImp::kSM_KeepState;
41 }
42
43 virtual int Handler(const EventImp &evt)
44 {
45 HandlerImp(evt);
46 return Callback(evt);
47 }
48
49public:
50 DimState() { std::cout << "DefCon" << std::endl; }
51 DimState(const std::string &n, const std::string s="STATE") : server(n),
52 service(n+"/"+s),
53 last(std::make_pair(Time(), kOffline)), cur(std::make_pair(Time(), kOffline))
54 {
55 }
56 virtual ~DimState()
57 {
58 }
59
60 /*const*/ std::string server;
61 /*const*/ std::string service;
62
63 std::pair<Time, int32_t> last;
64 std::pair<Time, int32_t> cur;
65 std::string msg;
66
67 virtual void Subscribe(StateMachineImp &imp)
68 {
69 imp.Subscribe(service)
70 (imp.Wrap(std::bind(&DimState::Handler, this, std::placeholders::_1)));
71 }
72
73 void SetCallback(const callback &cb)
74 {
75 fCallback = cb;
76 }
77
78 const Time &time() const { return cur.first; }
79 const int32_t &state() const { return cur.second; }
80
81 bool online() const { return state()>kOffline; }
82
83 virtual State description() const { return State(kNotAvailable, ""); }
84};
85
86inline std::ostream &operator<<(std::ostream& out, const DimState &s)
87{
88 const State rc = s.description();
89
90 out << s.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
91 out << kBold << s.server;
92
93 if (s.state()==DimState::kOffline)
94 return out << ": Offline";
95
96 if (rc.index==DimState::kNotAvailable)
97 return out;
98
99 out << ": ";
100
101// if (rc.index==-2)
102// out << s.state();
103// else
104 out << rc.name << "[" << rc.index << "]";
105
106 if (!rc.comment.empty())
107 out << " - " << kBlue << rc.comment;
108
109 return out;
110}
111
112
113class DimDescribedState : public DimState
114{
115 typedef std::function<void()> callback_desc;
116
117 callback_desc fCallbackStates;
118
119 virtual void CallbackStates()
120 {
121 if (fCallbackStates)
122 fCallbackStates();
123 }
124
125
126public:
127 DimDescribedState(const std::string &n) : DimState(n)
128 {
129 }
130
131 std::vector<State> states;
132
133 virtual void Subscribe(StateMachineImp &imp)
134 {
135 imp.Subscribe(server+"/STATE_LIST")
136 (imp.Wrap(std::bind(&DimDescribedState::HandleDesc, this, std::placeholders::_1)));
137
138 DimState::Subscribe(imp);
139 }
140
141 void SetCallbackStates(const callback_desc &cb)
142 {
143 fCallbackStates = cb;
144 }
145
146 int HandleDesc(const EventImp &evt)
147 {
148 if (evt.GetSize()>0)
149 {
150 states = State::SplitStates(evt.GetString());
151 states.push_back(State(kOffline, "Offline"));
152
153 CallbackStates();
154 }
155
156 return StateMachineImp::kSM_KeepState;
157 }
158
159 State description() const
160 {
161 for (auto it=states.begin(); it!=states.end(); it++)
162 if (it->index==state())
163 return *it;
164
165 return State(kNotAvailable, "n/a");
166 }
167};
168
169class DimDescriptions : public DimDescribedState
170{
171 typedef std::function<void()> callback_desc;
172
173 callback_desc fCallbackDescriptions;
174
175 virtual void CallbackDescriptions()
176 {
177 if (fCallbackDescriptions)
178 fCallbackDescriptions();
179 }
180
181public:
182 DimDescriptions(const std::string &n) : DimDescribedState(n)
183 {
184 }
185
186 std::vector<State> states;
187 std::vector<std::vector<Description>> descriptions;
188
189 virtual void Subscribe(StateMachineImp &imp)
190 {
191 imp.Subscribe(server+"/SERVICE_DESC")
192 (imp.Wrap(std::bind(&DimDescriptions::HandleServiceDesc, this, std::placeholders::_1)));
193
194 DimDescribedState::Subscribe(imp);
195 }
196
197 void SetCallbackDescriptions(const callback_desc &cb)
198 {
199 fCallbackDescriptions = cb;
200 }
201
202
203 int HandleServiceDesc(const EventImp &evt)
204 {
205 descriptions.clear();
206 if (evt.GetSize()>0)
207 {
208 std::string buf;
209 std::stringstream stream(evt.GetString());
210 while (getline(stream, buf, '\n'))
211 descriptions.push_back(Description::SplitDescription(buf));
212 }
213
214 CallbackDescriptions();
215
216 return StateMachineImp::kSM_KeepState;
217 }
218};
219
220class DimVersion : public DimState
221{
222 int Handler(const EventImp &evt)
223 {
224 HandlerImp(evt);
225
226 cur.second = evt.GetSize()==4 ? evt.GetInt() : kOffline;
227 if (cur.second==0)
228 cur.second=kOffline;
229
230 return Callback(evt);
231 }
232
233public:
234 DimVersion() : DimState("DIS_DNS", "VERSION_NUMBER") { }
235
236 std::string version() const
237 {
238 if (!online())
239 return "Offline";
240
241 std::ostringstream out;
242 out << "V" << state()/100 << 'r' << state()%100;
243 return out.str();
244 }
245
246 State description() const
247 {
248 return State(state(), version());
249 }
250};
251
252class DimControl : public DimState
253{
254 std::map<std::string, callback> fCallbacks;
255
256 int Handler(const EventImp &evt)
257 {
258 HandlerImp(evt);
259
260 shortmsg = msg;
261 file = "";
262 scriptdepth = -1;
263
264 // Evaluate msg
265 const size_t p0 = msg.find_first_of(':');
266 if (p0==std::string::npos)
267 return StateMachineImp::kSM_KeepState;
268
269 // Evaluate scriptdepth
270 const size_t ps = msg.find_first_of('-');
271 if (ps!=std::string::npos)
272 scriptdepth = atoi(msg.c_str()+ps+1);
273
274 // Find filename
275 const size_t p1 = msg.find_last_of('[');
276 if (p1==std::string::npos)
277 return StateMachineImp::kSM_KeepState;
278
279 const size_t p2 = msg.find_first_of(':', p0+1);
280
281 const size_t p3 = p2==std::string::npos || p2>p1 ? p1-1 : p2;
282
283 file = msg.substr(p0+2, p3-p0-2);
284
285 shortmsg.erase(p0, p3-p0);
286
287 const int rc = Callback(evt);
288
289 const auto func = fCallbacks.find(file);
290 if (func==fCallbacks.end())
291 return rc;
292
293 // Call callback
294 return func->second(evt);
295 }
296
297
298public:
299 DimControl() : DimState("DIM_CONTROL") { }
300
301 std::string file;
302 std::string shortmsg;
303 int scriptdepth;
304
305 void AddCallback(const std::string &script, const callback &cb)
306 {
307 fCallbacks[script] = cb;
308 }
309
310 State description() const
311 {
312 return State(state(), "Current label");
313 }
314};
315
316class DimDnsServerList
317{
318protected:
319 typedef std::function<void(const std::string &)> callback_srv;
320 typedef std::function<void(const EventImp &)> callback_evt;
321
322 callback_srv fCallbackServerAdd;
323 callback_srv fCallbackServerRemove;
324 callback_evt fCallbackServerEvent;
325
326 std::set<std::string> fServerList;
327
328 void HandlerServerImp(const EventImp &evt);
329
330 virtual void CallbackServerAdd(const std::string &str)
331 {
332 if (fCallbackServerAdd)
333 fCallbackServerAdd(str);
334 }
335 virtual void CallbackServerRemove(const std::string &str)
336 {
337 if (fCallbackServerRemove)
338 fCallbackServerRemove(str);
339 }
340 virtual void CallbackServerEvent(const EventImp &evt)
341 {
342 if (fCallbackServerEvent)
343 fCallbackServerEvent(evt);
344 }
345 virtual int HandlerServer(const EventImp &evt)
346 {
347 HandlerServerImp(evt);
348 CallbackServerEvent(evt);
349
350 return StateMachineImp::kSM_KeepState;
351 }
352
353public:
354 DimDnsServerList()
355 {
356 }
357 virtual ~DimDnsServerList()
358 {
359 }
360
361 Time time;
362 std::string msg;
363
364 virtual void Subscribe(StateMachineImp &imp)
365 {
366 imp.Subscribe("DIS_DNS/SERVER_LIST")
367 (imp.Wrap(std::bind(&DimDnsServerList::HandlerServer, this, std::placeholders::_1)));
368 }
369
370 void SetCallbackServerAdd(const callback_srv &cb)
371 {
372 fCallbackServerAdd = cb;
373 }
374
375 void SetCallbackServerRemove(const callback_srv &cb)
376 {
377 fCallbackServerRemove = cb;
378 }
379
380 void SetCallbackServerEvent(const callback_evt &cb)
381 {
382 fCallbackServerEvent = cb;
383 }
384
385 //const Time &time() const { return time; }
386 //const std::string &msg() const { return msg; }
387};
388
389struct Service
390{
391 std::string name;
392 std::string server;
393 std::string service;
394 std::string format;
395 bool iscmd;
396};
397
398inline bool operator<(const Service& left, const Service& right)
399{
400 return left.name < right.name;
401}
402
403class DimDnsServiceList : public DimDnsServerList
404{
405 StateMachineImp *fStateMachine;
406
407 typedef std::function<void(const Service &)> callback_svc;
408
409 callback_svc fCallbackServiceAdd;
410 //callback_evt fCallbackServiceEvt;
411
412 std::vector<std::string> fServiceList;
413
414 void CallbackServerAdd(const std::string &server)
415 {
416 fStateMachine->Subscribe(server+"/SERVICE_LIST")
417 (fStateMachine->Wrap(std::bind(&DimDnsServiceList::HandlerServiceList, this, std::placeholders::_1)));
418
419 DimDnsServerList::CallbackServerAdd(server);
420 }
421
422 void HandlerServiceListImp(const EventImp &evt);
423
424/*
425 virtual void CallbackServiceEvt(const EventImp &evt)
426 {
427 if (fCallbackServiceEvt)
428 fCallbackServiceEvt(evt);
429 }
430*/
431 virtual int HandlerServiceList(const EventImp &evt)
432 {
433 HandlerServiceListImp(evt);
434 //CallbackServiceEvent(evt);
435
436 return StateMachineImp::kSM_KeepState;
437 }
438
439
440 virtual void CallbackServiceAdd(const Service &service)
441 {
442 if (fCallbackServiceAdd)
443 fCallbackServiceAdd(service);
444 }
445
446public:
447 DimDnsServiceList() : fStateMachine(0)
448 {
449 }
450
451 void Subscribe(StateMachineImp &imp)
452 {
453 fStateMachine = &imp;
454 DimDnsServerList::Subscribe(imp);
455 }
456
457 void SetCallbackServiceAdd(const callback_svc &cb)
458 {
459 fCallbackServiceAdd = cb;
460 }
461/*
462 void SetCallbackServiceEvt(const callback_svc &cb)
463 {
464 fCallbackServiceEvt = cb;
465 }
466*/
467};
468
469#endif
Note: See TracBrowser for help on using the repository browser.