File indexing completed on 2025-08-02 08:21:07
0001
0002 #include "mongoose.h"
0003 #include "rcdaq.h"
0004
0005 #include <iostream>
0006 #include <sstream>
0007 #include <sys/stat.h>
0008
0009 using namespace std;
0010
0011 int update(struct mg_connection *nc, const char *key, const double value);
0012 int update(struct mg_connection *nc, const char *key, const int value);
0013 int update(struct mg_connection *nc, const char *key, const char *value);
0014 int trigger_updates(struct mg_connection *nc);
0015
0016 void initial_ws_update (struct mg_connection *nc);
0017 void send_ws_updates (struct mg_connection *nc);
0018 void send_updates (struct mg_connection *nc);
0019 void send_status (struct mg_connection *nc, std::string out);
0020 void send_error (struct mg_connection *nc, std::string out);
0021 void send_nothing (struct mg_connection *nc);
0022 void * mg_server (void *arg);
0023
0024 static void broadcast(struct mg_connection *nc, char *str, const int len);
0025
0026
0027 static struct mg_serve_http_opts s_http_server_opts;
0028
0029 int end_web_thread = 0;
0030
0031 pthread_mutex_t M_ws_send;
0032
0033 int error_flag = 0;
0034 std::string error_string = "";
0035
0036 static int last_runstate;
0037 static int last_runnumber;
0038 static int last_eventnumber;
0039 static double last_runvolume;
0040 static int last_runduration;
0041 static int last_openflag;
0042 static int last_serverflag;
0043 static int rcdaqname_request_flag;
0044 static int speed_request_flag = 0;
0045
0046 static int speed_update_interval =9;
0047
0048
0049
0050 int mg_end()
0051 {
0052 end_web_thread = 1;
0053 return 0;
0054 }
0055
0056 int request_mg_update (const int what)
0057 {
0058 switch (what)
0059 {
0060 case MG_REQUEST_NAME:
0061 rcdaqname_request_flag = 1;
0062 return 0;
0063 break;
0064
0065 case MG_REQUEST_SPEED:
0066 speed_request_flag = 1;
0067 return 0;
0068 break;
0069
0070 default:
0071 break;
0072 }
0073 return -1;
0074 }
0075
0076
0077
0078
0079
0080
0081
0082 std::string get_statusstring()
0083 {
0084 stringstream out;
0085
0086 if ( error_flag)
0087 {
0088 return error_string;
0089 }
0090 else if ( daq_running() )
0091 {
0092 out << "Running for " << get_runduration() << "s" << ends;
0093 }
0094 else
0095 {
0096 out << "Stopped Run " << get_oldrunnumber() << ends;
0097 }
0098 return out.str();
0099 }
0100
0101 std::string get_loggingstring()
0102 {
0103 stringstream out;
0104 if ( get_openflag())
0105 {
0106 if ( daq_running() )
0107 {
0108 if ( get_serverflag() )
0109 {
0110 out << "File on server: " << get_current_filename();
0111 return out.str();
0112 }
0113 else
0114 {
0115 out << "File: " << get_current_filename();
0116 return out.str();
0117 }
0118 }
0119 else
0120 {
0121 if ( get_serverflag() )
0122 {
0123 return "Logging enabled (Server)";
0124 }
0125 else
0126 {
0127 return "Logging enabled";
0128 }
0129 }
0130 }
0131 return "Logging disabled";
0132 }
0133
0134
0135 void initial_ws_update (struct mg_connection *nc)
0136 {
0137 char str[2048];
0138 int len;
0139
0140 int openvalue = get_openflag() | get_serverflag();
0141
0142 len = sprintf(str, "{ \"RunFlag\":%d, \"Status\":\"%s\" , \"RunNr\":%d , \"Events\":%d , \"Volume\":\"%f\", \"Duration\":%d, \"Logging\":\"%s\" ,\"Filename\":\"%s \" , \"OpenFlag\":%d , \"Name\":\"%s\" } "
0143 , daq_running()
0144 , get_statusstring().c_str()
0145 , get_runnumber()
0146 , get_eventnumber()
0147 , get_runvolume()
0148 , get_runduration()
0149 , get_loggingstring().c_str()
0150 , get_current_filename().c_str()
0151 , openvalue
0152 , daq_get_myname().c_str()
0153 );
0154
0155
0156 mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, str, len);
0157
0158
0159 }
0160
0161 static void broadcast(struct mg_connection *nc, char *str, const int len)
0162 {
0163 struct mg_connection *c;
0164
0165 for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c))
0166 {
0167 if ( c != nc)
0168 {
0169
0170
0171
0172 mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, str, len);
0173
0174 }
0175 }
0176 }
0177
0178
0179 int update(struct mg_connection *nc, const char *key, const double value)
0180 {
0181 char str[512];
0182 int len = sprintf(str, "{ \"%s\":%f }", key, value);
0183
0184 broadcast(nc, str, len);
0185 return 0;
0186 }
0187
0188 int update(struct mg_connection *nc, const char *key, const int value)
0189 {
0190 char str[512];
0191 int len = sprintf(str, "{ \"%s\":%d }", key, value);
0192
0193 broadcast(nc, str, len);
0194 return 0;
0195 }
0196
0197 int update(struct mg_connection *nc, const char *key, const char *value)
0198 {
0199 char str[512];
0200 int len = sprintf(str, "{ \"%s\":\"%s\" }", key, value);
0201
0202 broadcast(nc, str, len);
0203 return 0;
0204 }
0205
0206 void send_ws_updates (struct mg_connection *nc)
0207 {
0208 if ( daq_running() )
0209 {
0210
0211 update(nc, "Volume", get_runvolume());
0212 update(nc, "Events", get_eventnumber());
0213 update(nc, "Status", get_statusstring().c_str() );
0214 }
0215
0216 }
0217
0218 void send_updates (struct mg_connection *nc)
0219 {
0220 char str[512];
0221 int len;
0222
0223
0224 len = sprintf(str, "{ \"Events\":%d , \"Volume\":\"%f\" , \"Status\":\"%s\" }"
0225 , get_eventnumber()
0226 , get_runvolume()
0227 , get_statusstring().c_str()
0228 );
0229
0230
0231 nc->flags |= MG_F_SEND_AND_CLOSE;
0232 mg_printf(nc, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\n"
0233 "Content-Type: application/json\r\n\r\n%s",
0234 len, str);
0235
0236 }
0237
0238 void send_status (struct mg_connection *nc, std::string out)
0239 {
0240
0241
0242 ostringstream x;
0243 x<< endl;
0244
0245 out.replace(out.find(x.str()),x.str().length(),"");
0246
0247
0248
0249
0250 char str[512];
0251 int len;
0252 len = sprintf(str, "{ \"Status\":\"%s\" }"
0253 , out.c_str() );
0254
0255
0256 nc->flags |= MG_F_SEND_AND_CLOSE;
0257 mg_printf(nc, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\n"
0258 "Content-Type: application/json\r\n\r\n%s",
0259 len, str);
0260
0261
0262 }
0263
0264 void send_error (struct mg_connection *nc, std::string out)
0265 {
0266
0267
0268 ostringstream x;
0269 x<< endl;
0270
0271 out.replace(out.find(x.str()),x.str().length(),"");
0272
0273
0274
0275
0276
0277 nc->flags |= MG_F_SEND_AND_CLOSE;
0278 mg_printf(nc, "{ \"Status\":\"%s\" }", out.c_str());
0279
0280
0281 }
0282
0283 void send_nothing (struct mg_connection *nc)
0284 {
0285
0286
0287 nc->flags |= MG_F_SEND_AND_CLOSE;
0288 mg_printf(nc, "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n"
0289 "Content-Type: text/html\r\n\r\n");
0290
0291
0292 }
0293
0294
0295
0296
0297
0298 static void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
0299 {
0300 struct http_message *hm = (struct http_message *) ev_data;
0301 struct websocket_message *wm = (struct websocket_message *)ev_data;
0302 int status;
0303
0304 std::ostringstream out;
0305
0306
0307
0308 switch (ev)
0309 {
0310 case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
0311 {
0312
0313 nc->flags |= MG_F_USER_1;
0314 break;
0315 }
0316
0317 case MG_EV_WEBSOCKET_FRAME:
0318 {
0319 struct mg_str msg = {(char *) wm->data, wm->size};
0320
0321
0322 if ( mg_vcmp ( &msg, "daq_begin") == 0)
0323 {
0324
0325 status = daq_begin(0,out);
0326 if (status)
0327 {
0328 error_flag = 1;
0329 error_string = out.str();
0330 error_string.replace(error_string.find("\n"),1,"");
0331
0332 }
0333 else
0334 {
0335 error_flag = 0;
0336 error_string = "";
0337 }
0338
0339 return;
0340 }
0341
0342 else if ( mg_vcmp ( &msg, "daq_end") == 0)
0343 {
0344 status = daq_end(out);
0345 if (status)
0346 {
0347 send_error(nc,out.str() );
0348 }
0349 return;
0350 }
0351
0352 else if ( mg_vcmp ( &msg, "daq_open") == 0)
0353 {
0354
0355 daq_open();
0356 return;
0357 }
0358
0359 else if ( mg_vcmp ( &msg, "daq_close") == 0)
0360 {
0361
0362 daq_close();
0363 return;
0364 }
0365
0366 else if ( mg_vcmp ( &msg, "initial_update") == 0)
0367 {
0368
0369 initial_ws_update(nc);
0370 return;
0371 }
0372
0373 break;
0374 }
0375
0376 case MG_EV_HTTP_REQUEST:
0377 {
0378
0379
0380 if ( mg_vcmp ( &hm->uri, "/send_updates") == 0)
0381 {
0382 send_updates(nc);
0383 return;
0384 }
0385
0386 else if ( mg_vcmp ( &hm->uri, "/daq_begin") == 0)
0387 {
0388 status = daq_begin(0,out);
0389 if (status)
0390 {
0391 send_status(nc,out.str() );
0392 }
0393 else
0394 {
0395 send_nothing(nc);
0396 }
0397 return;
0398 }
0399
0400 else if ( mg_vcmp ( &hm->uri, "/daq_end") == 0)
0401 {
0402 status = daq_end(out);
0403 if (status)
0404 {
0405 send_status(nc,out.str() );
0406 }
0407 else
0408 {
0409 send_nothing(nc);
0410
0411 }
0412 return;
0413 }
0414
0415 else if ( mg_vcmp ( &hm->uri, "/daq_open") == 0)
0416 {
0417
0418 daq_open();
0419 send_nothing(nc);
0420 return;
0421 }
0422
0423 else if ( mg_vcmp ( &hm->uri, "/daq_close") == 0)
0424 {
0425
0426 daq_close();
0427 send_nothing(nc);
0428 return;
0429 }
0430
0431 mg_serve_http(nc, hm, s_http_server_opts);
0432 break;
0433 }
0434 case MG_EV_CLOSE:
0435 {
0436
0437
0438 break;
0439 }
0440 default:
0441 break;
0442 }
0443
0444
0445 }
0446
0447
0448
0449
0450 int trigger_updates(struct mg_connection *nc)
0451 {
0452 if ( error_flag)
0453 {
0454 update(nc, "Status", get_statusstring().c_str());
0455 error_flag = 0;
0456 }
0457
0458 if ( last_runstate != daq_running() )
0459 {
0460 last_runstate = daq_running();
0461 update(nc, "LINE", __LINE__);
0462 update(nc, "RunFlag", daq_running());
0463 update(nc, "Status", get_statusstring().c_str());
0464 update(nc, "RunNr", get_runnumber());
0465 update(nc, "Logging", get_loggingstring().c_str());
0466 }
0467
0468 if ( last_openflag != get_openflag() )
0469 {
0470 last_openflag = get_openflag();
0471 update(nc, "Logging", get_loggingstring().c_str());
0472 update(nc, "OpenFlag", get_openflag());
0473 }
0474 if ( last_serverflag != get_serverflag() )
0475 {
0476 last_serverflag = get_serverflag();
0477 update(nc, "Logging", get_loggingstring().c_str());
0478 update(nc, "ServerFlag", get_serverflag());
0479 }
0480
0481 if ( rcdaqname_request_flag )
0482 {
0483 rcdaqname_request_flag = 0;
0484 update(nc, "Name", daq_get_myname().c_str());
0485 }
0486
0487 if ( speed_request_flag )
0488 {
0489 speed_request_flag = 0;
0490 update(nc, "MBps", daq_get_mb_per_second());
0491 update(nc, "Evtps", daq_get_events_per_second());
0492 }
0493
0494 return 0;
0495 }
0496
0497 void * mg_server (void *arg)
0498 {
0499
0500 end_web_thread = 0;
0501 struct mg_mgr mgr;
0502 struct mg_connection *nc;
0503
0504 int port = (int) *(int *)arg;
0505 stringstream portstring;
0506 portstring << port << ends;
0507
0508 pthread_mutex_init( &M_ws_send, 0);
0509
0510
0511 last_runstate = daq_running();
0512 last_runnumber = get_runnumber();
0513 last_eventnumber = get_eventnumber();
0514 last_runvolume = get_runvolume();
0515 last_runduration = get_runduration();
0516 last_openflag = get_openflag();
0517 last_serverflag = get_serverflag();
0518 rcdaqname_request_flag = 0;
0519 speed_request_flag = 0;
0520
0521
0522
0523
0524 mg_mgr_init(&mgr, NULL);
0525 nc = mg_bind(&mgr, portstring.str().c_str(), ev_handler);
0526 if (nc == NULL)
0527 {
0528 cerr << __FILE__ << " " << __LINE__ << " Error starting server on port " << port << endl;
0529 return 0;
0530 }
0531
0532
0533 mg_set_protocol_http_websocket(nc);
0534 s_http_server_opts.document_root = HTMLDIR;
0535 s_http_server_opts.index_files = "control.html";
0536 s_http_server_opts.enable_directory_listing = "no";
0537
0538
0539 time_t last_time = time(0);
0540 time_t last_time_for_speed = last_time;
0541
0542 while(!end_web_thread)
0543 {
0544 mg_mgr_poll(&mgr, 1000);
0545
0546 if ( time(0) - last_time_for_speed > speed_update_interval)
0547 {
0548 if (daq_running() ) speed_request_flag = 1;
0549 last_time_for_speed = time(0);
0550 }
0551
0552 trigger_updates(nc);
0553
0554 if ( time(0) - last_time > 1)
0555 {
0556 send_ws_updates(nc);
0557 last_time = time(0);
0558 }
0559 }
0560
0561
0562 return 0;
0563 }