#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "modelbahn.h" #include "server.h" int Server::Start() { int err; pthread_attr_t attr; mtx = { 0 }; mtx = PTHREAD_MUTEX_INITIALIZER; thread_running = 1; pthread_attr_init (&attr); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE); err = pthread_create (&thread, &attr, ThreadEntry, this); if (err != 0) { debug (DEBUG_ERROR, (char*)"%s(%s:%d) pthread_create errror: %s", __FUNCTION__, __FILE__, __LINE__, strerror (errno)); running = 0; return 0; } return 1; }; Server::Server() { thread = 0; thread_running = 0; railways.SetSize(200, 200); status_text = "init server"; mode = SMODE_STARTUP; data_reset.mr_idx = -1; data_reset.mr_step = SMRESET_STEP_INIT; gettimeofday(&data_reset.mr_timestamp, NULL); Load (); }; Server::~Server() { if (IsChanged()) Save(); }; // // server thread will cycle as long as running is set to true // most important in each cycle there will be void Server::ThreadProcess() { int i = 0; int timeout10s; int cyclelooptime_max = 0; int cycletime_max = 0; struct timeval tv_loop, tv; gettimeofday (&tv, NULL); gettimeofday (&tv_loop, NULL); timeout10s = tv.tv_sec + 10; while (running) { interfaces.Loop(); turnouts.Loop(); // // startup process if (mode == SMODE_STARTUP) { mode = SMODE_MANUAL; printf ("%s:%d ************************************************************ fix me\n", __FILE__, __LINE__); // SetModeReset(); // currently there is not much to do. } // // reset all internal data else if (mode == SMODE_RESET) CycleModeReset(); // // mode manual else if (mode == SMODE_MANUAL) { } // // mode auto else if (mode == SMODE_AUTO) { } gettimeofday (&tv, NULL); i = (tv.tv_sec-tv_loop.tv_sec) * 1000 + (tv.tv_usec - tv_loop.tv_usec) / 1000; if (i > cycletime_max) cycletime_max = i; if (i < 25000 && i > 0) usleep (25000 - i*1000); gettimeofday (&tv, NULL); i = (tv.tv_sec-tv_loop.tv_sec) * 1000 + (tv.tv_usec - tv_loop.tv_usec) / 1000; if (i > cyclelooptime_max) cyclelooptime_max = i; if (tv_loop.tv_sec > timeout10s) { timeout10s = tv.tv_sec + 10; debug (DEBUG_INFO, "Server::ThreadProcess max Cycletime: %dms Cyclelooptime:%dms", cycletime_max, cyclelooptime_max); cycletime_max = 0; cyclelooptime_max = 0; } tv_loop = tv; } debug (0, "Server::ThreadProcess Finished"); thread_running = 0; }; void Server::LockThread() { pthread_mutex_lock (&mtx); }; void Server::UnLockThread() { pthread_mutex_unlock (&mtx); }; // // return JSONObject with all data void Server::GetJSONAll(JSONParse *json) { debug (DEBUG_INFO, "* Track::GetJSONAll data"); if (json == NULL) return; railways.GetJSONAll(json); interfaces.GetJSONAll(json); sensors.GetJSONAll(json); locomotives.GetJSONAll(json); turnouts.GetJSONAll(json); blocks.GetJSONAll(json); } bool Server::IsChanged() { if (railways.IsChanged() || interfaces.IsChanged() || locomotives.IsChanged() || sensors.IsChanged() || turnouts.IsChanged()) return true; else return false; } // // Set Mode Auto void Server::SetModeAuto() { debug (0, "%s:%d * Set Mode Auto", __FILE__, __LINE__); status_text = "Mode Auto"; } // // Set Mode Manual void Server::SetModeManual() { debug (0, "%s:%d * Set Mode Manual", __FILE__, __LINE__); mode = SMODE_MANUAL; status_text = "Mode Manual"; } // // run a single cycle in reset mode // each step will only reset one single step. #define INTERFACE_LOCO_TIME 250 #define INTERFACE_TURN_TIME 750 void Server::CycleModeReset() { JSONParse json; list elements; list::iterator iter; json.Clear(); // debug (0, "* CycleModeReset Step:%d", data_reset.mr_step); if (data_reset.mr_step == SMRESET_STEP_INIT) { // // init reset data_reset.mr_idx = -1; data_reset.mr_step++; } else if (data_reset.mr_step == SMRESET_STEP_LOCKS) { // // clear all locks debug (0, "* Clear all Locks", data_reset.mr_lastelm.c_str()); data_reset.mr_idx = -1; data_reset.mr_step++; } else if (data_reset.mr_step == SMRESET_STEP_INTERFACES) { // // clear locks data_reset.mr_idx = -1; data_reset.mr_step++; } else if (data_reset.mr_step == SMRESET_STEP_LOCOMOTIVES) { // // reset locomotives, cycle 30ms per locomotive if (data_reset.mr_idx < 0 || timer_get(&data_reset.mr_timestamp) > INTERFACE_LOCO_TIME) { if (data_reset.mr_idx < -1) data_reset.mr_idx = -1; data_reset.mr_idx++; data_reset.mr_lastelm = locomotives.GetName(data_reset.mr_idx); timer_start (&data_reset.mr_timestamp); if (data_reset.mr_lastelm.length() > 0) { debug (0, "* Reset Locomotive %s", data_reset.mr_lastelm.c_str()); LocomotiveSetReverse(data_reset.mr_lastelm, 0); LocomotiveSetSpeed(data_reset.mr_lastelm, 0); } else { data_reset.mr_idx = -1; data_reset.mr_step++; data_reset.mr_lastelm; } } } else if (data_reset.mr_step == SMRESET_STEP_TURNOUTS) { // // reset turnouts if (data_reset.mr_idx < 0 || timer_get(&data_reset.mr_timestamp) > INTERFACE_TURN_TIME) { int flags, active; if (data_reset.mr_idx < -1) data_reset.mr_idx = -1; data_reset.mr_idx++; data_reset.mr_lastelm = turnouts.GetName(data_reset.mr_idx); flags = turnouts.GetFlags(data_reset.mr_idx); if (flags & TURNOUT_F_TURNOUT) active = 1; else active = 0; timer_start (&data_reset.mr_timestamp); if (data_reset.mr_lastelm.length() > 0) { debug (0, "* Reset Turnout %s", data_reset.mr_lastelm.c_str()); TurnoutSet(data_reset.mr_lastelm, active); } else { data_reset.mr_idx = -1; data_reset.mr_step++; data_reset.mr_lastelm; } } } else if (data_reset.mr_step == SMRESET_STEP_SENSORS) { // // reset sensors // all can be done in one single cycle. // int i; // index of sensor int oldflags; // old flags Sensor sensor; // sensor data for (i = 0; sensors.Get(i, &sensor) == 1; i++) { oldflags = sensor.flags; sensor.flags &= ~(SENSOR_F_ACTIVE); debug (0, "* Reset Sensor: '%s' (%d -> %d)", sensor.name, oldflags, sensor.flags); if (oldflags != sensor.flags) // only update if needed sensors.Change(&sensor); } sensors.GetJSONAll(&json); data_reset.mr_idx = -1; data_reset.mr_step++; } else { SetModeManual(); } // // adding update data elements = json.GetElements(); for (iter = elements.begin(); iter != elements.end(); iter++) { if (network) network->ChangeListPushToAll("{"+(*iter).GetString()+"}"); } } // // Set Mode Error // FIXME: maybe adding error text as parameter? void Server::SetModeError(string text) { debug (0, "%s:%d * Set Mode Error :'%s'", __FILE__, __LINE__, text.c_str()); status_text = "Error:'" + text + "'"; } // // Set Mode Reset void Server::SetModeReset() { debug (0, "%s:%d * Set Reset Data", __FILE__, __LINE__); status_text = "Mode Reset"; mode = SMODE_RESET; data_reset.mr_step = SMRESET_STEP_INIT; data_reset.mr_idx = -1; data_reset.mr_lastelm = ""; gettimeofday(&data_reset.mr_timestamp, NULL); }; string Server::GetStatus(void) { string retval; LockThread(); retval = status_text; UnLockThread(); return retval; };