source: trunk/FACT++/src/evtserver.cc@ 17689

Last change on this file since 17689 was 17676, checked in by tbretz, 11 years ago
New program to display smartfact events from the previous night during daytime.
File size: 9.9 KB
Line 
1#include <valarray>
2
3#include "Dim.h"
4#include "Event.h"
5#include "Shell.h"
6#include "StateMachineDim.h"
7#include "Connection.h"
8#include "Configuration.h"
9#include "Console.h"
10
11#include "tools.h"
12
13#include "LocalControl.h"
14
15#include "HeadersFAD.h"
16#include "HeadersEventServer.h"
17
18#include "externals/fits.h"
19#include "externals/nova.h"
20
21namespace ba = boost::asio;
22namespace bs = boost::system;
23
24using namespace std;
25
26// ------------------------------------------------------------------------
27
28#include "DimDescriptionService.h"
29#include "DimState.h"
30
31// ------------------------------------------------------------------------
32
33class StateMachineEventServer : public StateMachineDim
34{
35 DimDescribedState fDimFadControl;
36
37 string fAuxPath;
38 string fOutPath;
39 uint32_t fStartDate;
40 uint32_t fNight;
41 uint32_t fInterval;
42
43 fits *fIn;
44
45 uint32_t fQoS;
46 double fTime;
47 //vector<float> fAvg;
48 //vector<float> fRms;
49 vector<float> fMax;
50 //vector<float> fPos;
51
52 Time fTimer;
53
54private:
55
56 int Execute()
57 {
58 if (GetCurrentState()==StateMachineImp::kSM_Ready)
59 return EventServer::State::kRunning;
60
61 // Nothing to do if not started
62 if (GetCurrentState()==EventServer::State::kIdle)
63 return EventServer::State::kIdle;
64
65 if (fDimFadControl.state()==FAD::State::kRunInProgress)
66 return EventServer::State::kStandby;
67
68 // Run only once in 5s
69 const Time now;
70 if (now<fTimer+boost::posix_time::milliseconds(fInterval))
71 return GetCurrentState();
72 fTimer = now;
73
74 // Running is only allowed when sun is up
75 const Nova::RstTime rst = Nova::GetSolarRst(now.JD()-0.5);
76 const bool isUp =
77 (rst.rise<rst.set && (now.JD()>rst.rise && now.JD()<rst.set)) ||
78 (rst.rise>rst.set && (now.JD()<rst.set || now.JD()>rst.rise));
79
80 if (!isUp)
81 return EventServer::State::kStandby;
82
83 // Check if file has to be changed
84 const uint32_t night = fStartDate>0 ? fStartDate : Time().NightAsInt()-1;
85
86 if (fNight!=night)
87 {
88 delete fIn;
89
90 const string name = fAuxPath + Tools::Form("/%04d/%02d/%02d/%08d.FAD_CONTROL_EVENT_DATA.fits", night/10000, (night/100)%100, night%100, night);
91
92 Info("Opening file "+name);
93
94 fIn = new fits(name);
95
96 if (!fIn->is_open())
97 {
98 Error(string("Opening file failed: ")+strerror(errno));
99 return StateMachineImp::kSM_Error;
100 }
101
102 fIn->SetRefAddress("QoS", fQoS);
103 fIn->SetRefAddress("Time", fTime);
104 fIn->SetVecAddress("max", fMax);
105 //fIn->SetVecAddress(fRms);
106 //fIn->SetVecAddress(fMax);
107 //fIn->SetVecAddress(fPos);
108 }
109
110 fNight = night;
111
112 // Get next data event
113 vector<float> sorted;
114 while (1)
115 {
116 if (!fIn->GetNextRow())
117 {
118 fNight = 0;
119 return EventServer::State::kRunning;
120 }
121
122 // Select a
123 if (fQoS & FAD::EventHeader::kAll)
124 continue;
125
126 for (int i=0; i<1440; i++)
127 fMax[i] /= 1000;
128
129 for (int i=8; i<1440; i+=9)
130 fMax[i] = fMax[i-2];
131
132 // construct output
133 sorted = fMax;
134 sort(sorted.begin(), sorted.end());
135
136 const double med = sorted[719];
137
138 vector<float> dev(1440);
139 for (int i=0; i<1440; i++)
140 dev[i] = fabs(sorted[i]-med);
141 sort(dev.begin(), dev.end());
142
143 const double deviation = dev[uint32_t(0.682689477208650697*1440)];
144
145 if (sorted[1439]>med+deviation*6)
146 break;
147 }
148
149 const double scale = max(0.25f, sorted[1436]);
150
151 ostringstream out;
152 out << Time(fTime+40587).JavaDate() << '\n';
153 out << "0\n";
154 out << scale << '\n';
155 out << setprecision(3);
156 out << "DEMO\nDEMO\nDEMO\x7f";
157 //out << sorted[1439] << '\n';
158 //out << sorted[719] << '\n';
159 //out << sorted[0] << '\x7f';
160
161 // The valid range is from 1 to 127
162 // \0 is used to seperate different curves
163 vector<uint8_t> val(1440);
164 for (uint64_t i=0; i<1440; i++)
165 {
166 float range = nearbyint(126*fMax[i]/scale); // [-2V; 2V]
167 if (range>126)
168 range=126;
169 if (range<0)
170 range=0;
171 val[i] = (uint8_t)range;
172 }
173
174 const char *ptr = reinterpret_cast<char*>(val.data());
175 out.write(ptr, val.size()*sizeof(uint8_t));
176 out << '\x7f';
177
178 if (fOutPath=="-")
179 Out() << out.str();
180 else
181 ofstream(fOutPath+"/cam-fadcontrol-eventdata.bin") << out.str();
182
183 return EventServer::State::kRunning;
184 }
185
186 int StartServer()
187 {
188 fStartDate = 0;
189 return EventServer::State::kRunning;
190 }
191
192 int StopServer()
193 {
194 delete fIn;
195 fIn = 0;
196
197 return EventServer::State::kIdle;
198 }
199
200 int StartDate(const EventImp &evt)
201 {
202 fStartDate = evt.GetUInt();
203 return EventServer::State::kRunning;
204 }
205
206
207public:
208 StateMachineEventServer(ostream &out=cout) : StateMachineDim(out, "EVENT_SERVER"),
209 fDimFadControl("FAD_CONTROL"), fStartDate(0), fNight(0), fIn(0), fMax(1440)
210
211 {
212 fDimFadControl.Subscribe(*this);
213
214 // State names
215 AddStateName(EventServer::State::kIdle, "Idle",
216 "Event server stopped.");
217 AddStateName(EventServer::State::kRunning, "Running",
218 "Reading events file and writing to output.");
219 AddStateName(EventServer::State::kStandby, "Standby",
220 "No events are processed, either the sun is down or fadctrl in kRunInProgress.");
221
222
223 AddEvent("START", EventServer::State::kIdle, StateMachineImp::kSM_Error)
224 (bind(&StateMachineEventServer::StartServer, this))
225 ("Start serving the smartfact camera file");
226
227 AddEvent("START_DATE", "I:1", EventServer::State::kIdle, StateMachineImp::kSM_Error)
228 (bind(&StateMachineEventServer::StartDate, this, placeholders::_1))
229 ("Start serving the smartfact camera file with the events from the given date"
230 "|uint32[yyyymmdd]:Integer representing the date from which the data should be read");
231
232 AddEvent("STOP", EventServer::State::kRunning, EventServer::State::kStandby, StateMachineImp::kSM_Error)
233 (bind(&StateMachineEventServer::StopServer, this))
234 ("Stop serving the smartfact camera file");
235 }
236 ~StateMachineEventServer()
237 {
238 delete fIn;
239 }
240
241 int EvalOptions(Configuration &conf)
242 {
243 fAuxPath = conf.Get<string>("aux-path");
244 fOutPath = conf.Get<string>("out-path");
245 fInterval = conf.Get<uint32_t>("interval");
246
247 return -1;
248 }
249};
250
251// ------------------------------------------------------------------------
252
253#include "Main.h"
254
255template<class T>
256int RunShell(Configuration &conf)
257{
258 return Main::execute<T, StateMachineEventServer>(conf);
259}
260
261void SetupConfiguration(Configuration &conf)
262{
263 po::options_description control("Event server options");
264 control.add_options()
265 ("aux-path", var<string>("/fact/aux"), "The root path to the auxilary files.")
266 ("out-path", var<string>("www/smartfact/data"), "Path where the output camera file should be written.")
267 ("interval", var<uint32_t>(5000), "Interval of updates in milliseconds.")
268 ;
269
270 conf.AddOptions(control);
271}
272
273/*
274 Extract usage clause(s) [if any] for SYNOPSIS.
275 Translators: "Usage" and "or" here are patterns (regular expressions) which
276 are used to match the usage synopsis in program output. An example from cp
277 (GNU coreutils) which contains both strings:
278 Usage: cp [OPTION]... [-T] SOURCE DEST
279 or: cp [OPTION]... SOURCE... DIRECTORY
280 or: cp [OPTION]... -t DIRECTORY SOURCE...
281 */
282void PrintUsage()
283{
284 cout <<
285 "The event server copies events from fits files to the smartfact data.\n"
286 "\n"
287 "Usage: evtserver [-c type] [OPTIONS]\n"
288 " or: evtserver [OPTIONS]\n";
289 cout << endl;
290}
291
292void PrintHelp()
293{
294 Main::PrintHelp<StateMachineEventServer>();
295
296 /* Additional help text which is printed after the configuration
297 options goes here */
298
299 /*
300 cout << "bla bla bla" << endl << endl;
301 cout << endl;
302 cout << "Environment:" << endl;
303 cout << "environment" << endl;
304 cout << endl;
305 cout << "Examples:" << endl;
306 cout << "test exam" << endl;
307 cout << endl;
308 cout << "Files:" << endl;
309 cout << "files" << endl;
310 cout << endl;
311 */
312}
313
314int main(int argc, const char* argv[])
315{
316 Configuration conf(argv[0]);
317 conf.SetPrintUsage(PrintUsage);
318 Main::SetupConfiguration(conf);
319 SetupConfiguration(conf);
320
321 if (!conf.DoParse(argc, argv, PrintHelp))
322 return 127;
323
324 //try
325 {
326 // No console access at all
327 if (!conf.Has("console"))
328 {
329// if (conf.Get<bool>("no-dim"))
330// return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
331// else
332 return RunShell<LocalStream>(conf);
333 }
334 // Cosole access w/ and w/o Dim
335/* if (conf.Get<bool>("no-dim"))
336 {
337 if (conf.Get<int>("console")==0)
338 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
339 else
340 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
341 }
342 else
343*/ {
344 if (conf.Get<int>("console")==0)
345 return RunShell<LocalShell>(conf);
346 else
347 return RunShell<LocalConsole>(conf);
348 }
349 }
350 /*catch (std::exception& e)
351 {
352 cerr << "Exception: " << e.what() << endl;
353 return -1;
354 }*/
355
356 return 0;
357}
Note: See TracBrowser for help on using the repository browser.