You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Modelbahn/server/server.cc

245 lines
4.8 KiB

#include <string>
#include <sys/time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
#include <math.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <pthread.h>
#include <sys/syscall.h>
#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;
while (running) {
interfaces.Loop();
turnouts.Loop();
//
// startup process
if (mode == SMODE_STARTUP) {
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) {
}
usleep (25000);
}
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);
}
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.
void Server::CycleModeReset() {
JSONParse json;
list<JSONElement> elements;
list<JSONElement>::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_step++;
}
else if (data_reset.mr_step == SMRESET_STEP_INTERFACES) {
//
// reset interfaces
data_reset.mr_step++;
}
else if (data_reset.mr_step == SMRESET_STEP_LOCOMOTIVES) {
//
// reset locomotives
data_reset.mr_step++;
}
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_step++;
}
else if (data_reset.mr_step == SMRESET_STEP_TURNOUTS) {
//
// reset turnouts
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;
};