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/block.cc

507 lines
10 KiB

#include <string>
#include "modelbahn.h"
#include "block.h"
#include <list>
#include <string>
#include <string.h>
using namespace std;
Blocks::Blocks () {
changed = 0;
blocks = (Block*) malloc(sizeof(Block)*SENSORS_MAX);
max = BLOCKS_MAX;
last_blockidx = -1;
};
Blocks::~Blocks() {
free (blocks);
blocks = NULL;
max = 0;
};
int Blocks::Lock() {
if (pthread_mutex_lock(&mtx) == 0) return 1;
else return 0;
}
int Blocks::UnLock() {
if (pthread_mutex_unlock(&mtx) == 0) return 1;
else return 0;
}
JSONParse Blocks::_GetJSON(Block *bl) {
JSONParse json;
JSONElement je;
json.Clear();
json.AddObject("name", bl->name);
json.AddObject("flags", bl->flags);
json.AddObject("lockedby", bl->lockedby);
json.AddObject("sensor_enter_0", bl->s_enter[0]);
json.AddObject("sensor_slow_0", bl->s_slow[0]);
json.AddObject("sensor_stop_0", bl->s_stop[0]);
json.AddObject("sensor_shortstop_0", bl->s_shortstop[0]);
json.AddObject("sensor_enter_1", bl->s_enter[1]);
json.AddObject("sensor_slow_1", bl->s_slow[1]);
json.AddObject("sensor_stop_1", bl->s_stop[1]);
json.AddObject("sensor_shortstop_1", bl->s_shortstop[1]);
json.AddObject("secondblock", bl->secondblock);
return json;
};
JSONParse Blocks::GetJSON(string name) {
int i;
JSONParse jp;
jp.Clear();
Lock();
for (i = 0; i < max; i++) if (blocks[i].name[0] != 0) {
if (name.compare(blocks[i].name) == 0) {
jp = _GetJSON(i);
}
}
UnLock();
return jp;
};
void Blocks::GetJSONAll(JSONParse *json) {
int i, cnt;
JSONElement je;
Lock();
//
// write all railway data
// create json object array manualy
je.type = JSON_T_ARRAY;
je.name = "blocks";
for (cnt = 0, i = 0; i < max; i++)
if (blocks[i].name[0] != 0) {
if (cnt != 0) je.value += ","; // not first element
je.value += _GetJSON(i).ToString();
cnt++;
}
json->AddObject(je);
UnLock();
};
Block Blocks::GetBlockFromJSON(JSONParse *j) {
Block bl;
string s;
bl.name[0] = 0;
bl.secondblock[0] = 0;
bl.flags = 0;
bl.lockedby[0] = 0;
j->GetValue("name", &s);
strncpy (bl.name, s.c_str(), REFERENCENAME_LEN);
j->GetValueInt("flags", &bl.flags);
// j->GetValue("lockedby", &s);
// strncpy (bl.lockedby, s.c_str(), REFERENCENAME_LEN);
//
// old version input data
//
s = "";
if (j->GetValue("sensor_pos_1", &s)) {
strncpy (bl.s_enter[0], s.c_str(), REFERENCENAME_LEN);
strncpy (bl.s_stop[1], s.c_str(), REFERENCENAME_LEN);
}
s = "";
if (j->GetValue("sensor_center", &s)) {
strncpy (bl.s_shortstop[0], s.c_str(), REFERENCENAME_LEN);
strncpy (bl.s_shortstop[1], s.c_str(), REFERENCENAME_LEN);
}
s = "";
if (j->GetValue("sensor_neg_1", &s)) {
strncpy (bl.s_enter[1], s.c_str(), REFERENCENAME_LEN);
strncpy (bl.s_stop[0], s.c_str(), REFERENCENAME_LEN);
}
//
// new version
//
s = ""; if (j->GetValue("sensor_enter_0", &s)) strncpy (bl.s_enter[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_enter_1", &s)) strncpy (bl.s_enter[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_slow_0", &s)) strncpy (bl.s_slow[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_slow_1", &s)) strncpy (bl.s_slow[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_stop_0", &s)) strncpy (bl.s_stop[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_stop_1", &s)) strncpy (bl.s_stop[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_shortstop_0", &s)) strncpy (bl.s_shortstop[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_shortstop_1", &s)) strncpy (bl.s_shortstop[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("secondblock", &s)) strncpy (bl.secondblock, s.c_str(), REFERENCENAME_LEN);
printf ("%s:%d block: %s flags: %d\n", __FILE__, __LINE__, bl.name, bl.flags);
return bl;
};
int Blocks::Change(Block *bl) {
int i;
int ifree = -1;
Lock();
for (i = 0; i < max; i++) {
if (blocks[i].name[0] != 0) {
// found element
if (strncmp(blocks[i].name, bl->name, REFERENCENAME_LEN) == 0) {
ifree = i;
break;
}
}
else if (ifree == -1) ifree = i;
}
// element not found add new element
if (ifree != -1 && ifree < max) {
blocks[ifree] = *bl;
strncpy (blocks[ifree].name, bl->name, REFERENCENAME_LEN);
}
changed = 1;
UnLock();
return 1;
};
int Blocks::Delete(string name) {
int i;
Lock();
for (i = 0; i < max; i++) if (blocks[i].name[0] != 0) {
if (name.compare(blocks[i].name) == 0) {
blocks[i].name[0] = 0;
blocks[i].flags = 0;
changed = 1;
break;
}
}
UnLock();
return 1;
};
//
// thread will not be locked..
int Blocks::SetOff(string blname) {
Block *bl = NULL;
JSONParse jp;
Lock();
if ((bl = FindBlock(blname)) != NULL) {
changed = 1;
bl->flags |= BLOCK_F_OFF;
debug (0, "Blocks::SetOff block %s", bl->name);
jp.AddObject("block",_GetJSON(bl));
if(network) network->ChangeListPushToAll(jp.ToString());
UnLock();
return 1;
}
UnLock();
return 1;
};
int Blocks::IsOff(string blname) {
// return -1 if not found, 0 on no lock, 1 on lock
Block *bl = NULL;
int res = -1;
Lock();
if ((bl = FindBlock(blname)) != NULL) {
if (bl->flags & BLOCK_F_OFF) res = 1;
else res = 0;
}
UnLock();
return res;
};
int Blocks::SetLockedby (string blname, string lockedby, int lock_onoff) {
// return -1 if not found, 0 on no lock, 1 on lock
Block *bl = NULL;
JSONParse jp;
int res = -1;
int x, y, cnt;
debug (0, "Blocks::SetLockedby block:'%s' locked for '%s' locked:%d", blname.c_str(), lockedby.c_str(), lock_onoff);
Lock();
if ((bl = FindBlock(blname)) != NULL) {
if (lockedby.compare (bl->lockedby) == 0 || bl->lockedby[0] == 0) {
if (lock_onoff) strncpy (bl->lockedby, lockedby.c_str(), REFERENCENAME_LEN);
else bl->lockedby[0] = 0;
jp.AddObject("block",_GetJSON(bl));
if(network) network->ChangeListPushToAll(jp.ToString());
x = -1; y = -1;
cnt = 0;
while (server->railways.FindReference(&x, &y, blname, (cnt++))) {
server->railways.SetLockedby(x, y, lockedby, lock_onoff);
}
res = 1;
}
else {
debug (0, "Blocks::SetLockedby could not set block '%s' for '%s'. Is used by '%s'.", blname.c_str(),lockedby.c_str(), bl->lockedby);
res = 0;
}
}
else {
debug (0, "Blocks::SetLockedby could not find block '%s'.", blname.c_str());
}
UnLock();
return res;
};
string Blocks::GetLockedby (string blname) {
Block *bl = NULL;
string lb;
Lock();
if ((bl = FindBlock(blname)) != NULL) {
lb = bl->lockedby;
UnLock();
return lb;
}
UnLock();
return "";
};
string Blocks::GetSecondBlock(string block) {
Block *bl = NULL;
string sb;
Lock();
if ((bl = FindBlock(block)) != NULL) {
sb = bl->secondblock;
UnLock();
return sb;
}
UnLock();
return "";
}
Block* Blocks::FindBlock(string name) {
Block *bl = NULL;
if (last_blockidx >= 0 && last_blockidx < max)
if (name.compare (blocks[last_blockidx].name) == 0)
return &blocks[last_blockidx];
for (last_blockidx = 0; last_blockidx < max; last_blockidx++) {
if (name.compare (blocks[last_blockidx].name) == 0)
return &blocks[last_blockidx];
}
return bl;
};
int Blocks::Clear(string name) {
Block *bl = NULL;
Lock();
if ((bl = FindBlock(name)) != NULL) {
changed = 1;
bl->flags &= ~BLOCK_F_OFF;
printf ("%s:%d clear block %s off", __FILE__, __LINE__, bl->name);
UnLock();
return 1;
}
UnLock();
return 0;
};
void Blocks::ClearLockedby(string name) {
int i;
JSONParse jp;
Lock();
for (i = 0; i < max; i++) {
if (name.compare(blocks[i].lockedby) == 0) {
blocks[i].lockedby[0] = 0;
changed = 1;
jp.AddObject("block",_GetJSON(i));
if(network) network->ChangeListPushToAll(jp.ToString());
}
}
UnLock();
};
int Blocks::GetFlags (string blname) {
int res = 0;
int i;
JSONParse jp;
Lock();
for (i = 0; i < max; i++) if (blname.compare(blocks[i].name) == 0) {
res = blocks[i].flags;
}
UnLock();
return res;
};
/*
* return a pointer to the blockdata in case of split blocks also return the second block
*/
int Blocks::GetBlocksPtr (string blname, Block **b1, Block **b2) {
int i;
(*b1) = NULL;
(*b2) = NULL;
for (i = 0; i < max; i++) if (blname.compare(blocks[i].name) == 0) {
(*b1) = &blocks[i];
}
if ((*b1) == NULL) {
debug (0, "Blocks::%s Could not find block: %s", __FUNCTION__, blname.c_str());
return 0;
}
if ((*b1)->flags & BLOCK_F_SPLIT) {
for (i = 0; i < max; i++) if (strcmp ((*b1)->secondblock, blocks[i].name) == 0) {
(*b2) = &blocks[i];
}
if ((*b2) == NULL) {
debug (0, "Blocks::%s Could not find second block: %s", __FUNCTION__, (*b1)->secondblock);
return 0;
}
}
return 1;
}
string Blocks::GetSensorEnter (int direction, string blname, int locoflags) {
string res = "";
JSONParse jp;
Block *b1 = NULL;
Block *b2 = NULL;
Lock();
if (!GetBlocksPtr(blname, &b1, &b2)) return res;
if (!(locoflags & LOCO_F_SHORTTRAIN) && (b1->flags & BLOCK_F_SPLIT)) {
if (direction == 0) {
if (b1->flags & BLOCK_F_SPLITPOS) res = b1->s_enter[direction];
else res = b2->s_enter[direction];
}
else {
if (b1->flags & BLOCK_F_SPLITPOS) res = b2->s_enter[direction];
else res = b1->s_enter[direction];
}
}
if (res.length() == 0) {
res = b1->s_enter[direction];
}
UnLock();
return res;
};
string Blocks::GetSensorSlow (int direction, string blname, int locoflags) {
string res = "";
JSONParse jp;
Block *b1 = NULL;
Block *b2 = NULL;
Lock();
if (!GetBlocksPtr(blname, &b1, &b2)) return res;
if (!(locoflags & LOCO_F_SHORTTRAIN) && (b1->flags & BLOCK_F_SPLIT)) {
if (direction == 0) {
if (b1->flags & BLOCK_F_SPLITPOS) res = b2->s_slow[direction];
else res = b1->s_slow[direction];
}
else {
if (b1->flags & BLOCK_F_SPLITPOS) res = b1->s_slow[direction];
else res = b2->s_slow[direction];
}
}
if (res.length() == 0) {
res = b1->s_slow[direction];
}
if (res.length() == 0) {
res = b1->s_enter[direction];
}
UnLock();
return res;
};
string Blocks::GetSensorStop (int direction, string blname, int locoflags) {
string res = "";
JSONParse jp;
Block *b1 = NULL;
Block *b2 = NULL;
Lock();
if (!GetBlocksPtr(blname, &b1, &b2)) return res;
if ((locoflags & LOCO_F_SHORTTRAIN) && b1->s_shortstop[direction][0] != 0)
res = b1->s_shortstop[direction];
if (!(locoflags & LOCO_F_SHORTTRAIN) && (b1->flags & BLOCK_F_SPLIT)) {
if (direction == 0) {
if (b1->flags & BLOCK_F_SPLITPOS) res = b2->s_stop[direction];
else res = b1->s_stop[direction];
}
else {
if (b1->flags & BLOCK_F_SPLITPOS) res = b1->s_stop[direction];
else res = b2->s_stop[direction];
}
}
if (res.length() == 0) {
res = b1->s_stop[direction];
}
UnLock();
return res;
};