origin
steffen 5 years ago
parent b5a6396a18
commit 62f450ba97

@ -8,6 +8,7 @@ Blocks::Blocks () {
changed = 0;
blocks = (Block*) malloc(sizeof(Block)*SENSORS_MAX);
max = BLOCKS_MAX;
last_blockidx = -1;
};
Blocks::~Blocks() {
@ -31,19 +32,19 @@ int Blocks::UnLock() {
}
JSONParse Blocks::_GetJSON(int idx) {
JSONParse Blocks::_GetJSON(Block *bl) {
JSONParse json;
JSONElement je;
string s = "";
json.Clear();
s = blocks[idx].name; json.AddObject("name", s);
json.AddObject("flags", blocks[idx].flags);
json.AddObject("lockedby", blocks[idx].lockedby);
json.AddObject("sensor_pos_1", blocks[idx].s_pos_1);
json.AddObject("sensor_center", blocks[idx].s_center);
json.AddObject("sensor_neg_1", blocks[idx].s_neg_1);
s = bl->name; json.AddObject("name", s);
json.AddObject("flags", bl->flags);
json.AddObject("lockedby", bl->lockedby);
json.AddObject("sensor_pos_1", bl->s_pos_1);
json.AddObject("sensor_center", bl->s_center);
json.AddObject("sensor_neg_1", bl->s_neg_1);
return json;
};
@ -163,36 +164,115 @@ int Blocks::Delete(string name) {
return 1;
};
//
// thread will not be locked..
int Blocks::SetOff(string name) {
int i;
int Blocks::SetOff(string blname) {
Block *bl = NULL;
JSONParse jp;
for (i = 0; i < max; i++) if (blocks[i].name[0] != 0) {
if (name.compare(blocks[i].name) == 0) {
Lock();
if ((bl = FindBlock(blname)) != NULL) {
changed = 1;
blocks[i].flags |= BLOCK_F_OFF;
printf ("%s:%d set block %s off", __FILE__, __LINE__, blocks[i].name);
break;
}
bl->flags |= BLOCK_F_OFF;
printf ("%s:%d set block %s off", __FILE__, __LINE__, bl->name);
jp.AddObject("block",_GetJSON(bl));
if(network) network->ChangeListPushToAll(jp.ToString());
UnLock();
return 1;
}
UnLock();
return 1;
};
int Blocks::Clear(string name) {
int i;
int Blocks::IsOff(string blname) {
// return -1 if not found, 0 on no lock, 1 on lock
Block *bl = NULL;
int res = -1;
for (i = 0; i < max; i++) if (blocks[i].name[0] != 0) {
if (name.compare(blocks[i].name) == 0) {
changed = 1;
blocks[i].flags &= ~BLOCK_F_OFF;
printf ("%s:%d clear block %s off", __FILE__, __LINE__, blocks[i].name);
break;
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;
Lock();
if ((bl = FindBlock(blname)) != NULL) {
if (lockedby.compare (bl->lockedby) == 0) res = 1;
else if (bl->lockedby[0] == 0) {
strncpy (bl->lockedby, lockedby.c_str(), REFERENCENAME_LEN);
jp.AddObject("block",_GetJSON(bl));
if(network) network->ChangeListPushToAll(jp.ToString());
res = 1;
}
else res = 0;
}
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 "";
};
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;
};

@ -33,7 +33,11 @@ class Blocks {
int UnLock();
// not thread safe
JSONParse _GetJSON(int idx);
JSONParse _GetJSON(Block *bl);
JSONParse _GetJSON(int idx) { return _GetJSON(&blocks[idx]); };
int last_blockidx; // to speed up things
Block* FindBlock(string name);
public:
Blocks();
~Blocks();
@ -48,7 +52,12 @@ class Blocks {
void GetJSONAll(JSONParse *json);
Block GetBlockFromJSON(JSONParse *j);
int SetOff(string name);
int SetOff(string blname);
int IsOff(string blname);
int SetLockedby (string blname, string lockedby, int lock_onoff);
string GetLockedby (string blname);
int Clear(string name);
};

@ -265,6 +265,7 @@ int Locomotives::SetFunction(string name, int func, int value) {
int Locomotives::SetDestination (string name, string block, int direction) {
int i;
string next;
Lock();
for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0)
@ -272,10 +273,14 @@ int Locomotives::SetDestination (string name, string block, int direction) {
debug (0, "Locomotives::SetDestination (Name:%s Block:%s Direction:%d)\n", name.c_str(), block.c_str(), direction);
if (direction) snprintf (locomotives[i].blockdest, REFERENCENAME_LEN, "-:%s", block.c_str());
else snprintf (locomotives[i].blockdest, REFERENCENAME_LEN, "+:%s", block.c_str());
server->railways.FindWay(locomotives[i].blockassign, locomotives[i].blockdest, locomotives[i].name, &next);
break;
}
UnLock();
printf ("%s:%d %s ************** finish me **************\n", __FILE__, __LINE__, __FUNCTION__);
return 1;
}

@ -89,7 +89,7 @@ void Network::ThreadProcess() {
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 < 1000 && i > 0) usleep (100000 - i*1000);
if (i < 100 && i > 0) usleep (100000 - 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;
@ -153,7 +153,6 @@ void Network::ChangeListPushToAll(string changes) {
int Network::ServerLoop() {
UNIX *u = NULL;
if (sockserver.IsData(10)) {
u = sockserver.Accept();
clients.push_back(u);

@ -37,6 +37,81 @@ int Railways::UnLock() {
};
//
// data must be mutex looked before use
struct s_findway_data Railways::NextPos(struct s_findway_data pos, int dirtype) {
struct s_findway_data np = { x: -1, y: -1, enterfrom: -1, parma: pos.parma }; // newpos
if (dirtype == 1) {
if (pos.enterfrom == EF_NORTH) {
np.x = pos.x;
np.y = pos.y + 1 ;
np.enterfrom = EF_NORTH;
} else if (pos.enterfrom == EF_SOUTH) {
np.x = pos.x;
np.y = pos.y - 1;
np.enterfrom = EF_SOUTH;
}
}
else if (dirtype == 2) {
if (pos.enterfrom == EF_WEST) {
np.x = pos.x + 1;
np.y = pos.y;
np.enterfrom = EF_WEST;
} else if (pos.enterfrom == EF_EAST) {
np.x = pos.x - 1;
np.y = pos.y;
np.enterfrom = EF_EAST;
}
}
else if (dirtype == 3) {
if (pos.enterfrom == EF_WEST) {
np.x = pos.x;
np.y = pos.y - 1;
np.enterfrom = EF_SOUTH;
} else if (pos.enterfrom == EF_NORTH){
np.x = pos.x - 1;
np.y = pos.y;
np.enterfrom = EF_EAST;
}
}
else if (dirtype == 4) {
if (pos.enterfrom == EF_NORTH) {
np.x = pos.x + 1;
np.y = pos.y;
np.enterfrom = EF_WEST;
} else if (pos.enterfrom == EF_EAST){
np.x = pos.x;
np.y = pos.y - 1;
np.enterfrom = EF_SOUTH;
}
}
else if (dirtype == 5) {
if (pos.enterfrom == EF_SOUTH) {
np.x = pos.x + 1;
np.y = pos.y;
np.enterfrom = EF_WEST;
} else if (pos.enterfrom == EF_EAST){
np.x = pos.x;
np.y = pos.y + 1;
np.enterfrom = EF_NORTH;
}
}
else if (dirtype == 6) {
if (pos.enterfrom == EF_WEST) {
np.x = pos.x;
np.y = pos.y + 1;
np.enterfrom = EF_NORTH;
} else if (pos.enterfrom == EF_SOUTH){
np.x = pos.x - 1;
np.y = pos.y;
np.enterfrom = EF_EAST;
}
}
return np;
};
//
// return index inside the array (clip to boundery)
@ -319,7 +394,8 @@ void Railways::ClearLockedby(string name) {
}
int Railways::FindReference(int *x, int *y, string name) {
int Railways::_FindReference(int *x, int *y, string name) {
int found = 0;
if (x == NULL || y == NULL) return 0;
if (*x < 0 || *y < 0) {
@ -327,7 +403,8 @@ int Railways::FindReference(int *x, int *y, string name) {
*y = 0;
}
Lock();
printf ("%s:%d find reference (%d,%d,%s)\n", __FILE__, __LINE__, *x, *y, name.c_str());
for (; found == 0 && *y < height; (*y)++) {
if (*x >= width) *x = 0;
else (*x)++;
@ -338,15 +415,269 @@ int Railways::FindReference(int *x, int *y, string name) {
break;
}
}
if (found) break;
}
UnLock();
printf ("%s:%d found (%d,%d)\n", __FILE__, __LINE__, *x, *y);
if (*x < width && *y < height) return 1;
else return 0;
};
int FindWay(string blockstart, string blockend, string lockedfor, string *next) {
int Railways::FindReference(int *x, int *y, string name) {
int res;
Lock();
res = _FindReference (x, y, name);
UnLock();
return res;
};
void Railways::DebugPrintFindWay(struct s_findway_map *fw) {
string c;
int x, y;
int idx;
char chr;
printf (" ");
for (x = 0; x < width && x < 80; x++)
printf ("%c", (char) ((x % 10) + '0'));
printf ("\n");
for (y = 0; y < height && y < 40; y++) {
printf ("%c ", (char) ((y % 10) + '0'));
for (x = 0; x < width && x < 80; x++) {
idx = GetRIdx(x, y);
if (railways[idx].dir == 1) c = "";
if (railways[idx].dir == 2) c = "";
if (railways[idx].dir == 3) c = "";
if (railways[idx].dir == 4) c = "";
if (railways[idx].dir == 5) c = "";
if (railways[idx].dir == 6) c = "";
if (railways[idx].type == RAILWAY_CROSSING) c = "+";
if (railways[idx].type == RAILWAY_TURNOUT) c = "t";
if (railways[idx].type == RAILWAY_CONNECTOR) c = "";
if (railways[idx].type == RAILWAY_BLOCK && railways[idx].dir == 1) c = "";
if (railways[idx].type == RAILWAY_BLOCK && railways[idx].dir == 2) c = "";
if (fw != NULL) {
if ((fw[idx].e & 15) > 0) {
chr = (char)('0' + (fw[idx].e & 15));
if (chr > '9') chr = chr - ('0' + 10) + 'A';
c = chr;
}
else if (fw[idx].e != 0) {
c = "?";
printf ("---%d---", fw[idx].e);
}
}
printf ("%s", c.c_str());
c = " ";
}
printf ("\n");
}
for (x = 0; x < width && x < 80; x++)
printf ("%c", (char) ((x % 10) + '0'));
printf ("\n");
printf ("Debug Finished\n");
}
// return 0 if no way found
int Railways::FindWay(string blockstart, string blockend, string lockedfor, string *next) {
// direction 0 ... RIGHT and DOWN
// direction 1 ... LEFT and UP
struct s_findway_data fd_pos;
struct s_findway_data fd_tmp;
struct s_findway_data fd_start;
struct s_findway_data fd_end;
Railway *rpos, *rnext;
std::list<struct s_findway_data> fd_list;
struct s_findway_map *fd_data = NULL;
string lockedby;
int i, x ,y;
int found = 0;
// check blocklen
if (blockstart.length() <= 3 || blockend.length() <= 3) return 0;
// allocate and clear memory for checked data
fd_data = (struct s_findway_map *) malloc (sizeof(struct s_findway_map) * width * height);
if (fd_data == NULL) {
printf ("%s:%d (%s) FATAL ERROR: could not allocate enough memory\n", __FILE__, __LINE__, __FUNCTION__);
exit (1);
}
memset (fd_data, 0x0, sizeof(struct s_findway_map) * width*height);
//
// find start and endpoint mark on fd_data, also startpoint to fd_list
fd_end.x = fd_start.x = -1;
fd_end.y = fd_start.y = -1;
fd_end.enterfrom = fd_start.enterfrom = -1;
fd_end.parma = fd_start.parma = -1;
if (FindReference(&fd_start.x, &fd_start.y, blockstart.substr(2, string::npos))) {
if (Get(fd_start.x, fd_start.y).dir == 1) {
if (blockstart[0] == '+') fd_start.enterfrom = 0;
else fd_start.enterfrom = 2;
}
else {
if (blockstart[0] == '+') fd_start.enterfrom = 3;
else fd_start.enterfrom = 1;
}
fd_data[GetRIdx(fd_start.x, fd_start.y)].e = (1 << fd_start.enterfrom);
fd_data[GetRIdx(fd_start.x, fd_start.y)].score = 1;
fd_start.parma = 1;
}
else {
debug (0, "Railway::FindWay could not find startblock (%s).", blockstart.c_str());
free (fd_data);
return 0;
}
if (FindReference(&fd_end.x, &fd_end.y, blockend.substr(2, string::npos))) {
if (Get(fd_end.x, fd_end.y).dir == 1) {
if (blockend[0] == '+') fd_end.enterfrom = 0;
else fd_end.enterfrom = 2;
}
else {
if (blockend[0] == '+') fd_end.enterfrom = 3;
else fd_end.enterfrom = 1;
}
fd_data[GetRIdx(fd_end.x, fd_end.y)].e = (1 << fd_end.enterfrom);
}
else {
debug (0, "Railway::FindWay could not find endblock (%s).", blockend.c_str());
free (fd_data);
return 0;
}
fd_pos = NextPos(fd_start, Get(fd_start.x, fd_start.y).dir);
// fd_list.push_back(fd_pos);
Lock();
//
// loop through the map; if found next needs to be filled in
while ((fd_list.size() > 0 || fd_pos.enterfrom >= 0) && found == 0) {
DebugPrintFindWay(fd_data);
if (fd_pos.enterfrom < 0) {
std::list<struct s_findway_data>::iterator iter;
iter = fd_list.begin();
if (iter != fd_list.end()) {
fd_pos = *iter;
fd_list.pop_front();
printf ("get from stack (%d,%d)\n", fd_pos.x, fd_pos.y);
}
}
printf ("%s:%d fd_start (%d,%d) enterfrom:%d\n", __FILE__, __LINE__, fd_start.x, fd_start.y, fd_start.enterfrom);
printf ("%s:%d fd_end (%d,%d) enterfrom:%d\n", __FILE__, __LINE__, fd_end.x, fd_end.y, fd_end.enterfrom);
printf ("%s:%d fd_pos (%d,%d) enterfrom:%d\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_pos.enterfrom);
if (fd_pos.enterfrom < 0 && fd_pos.enterfrom > 3) {
fd_pos.enterfrom = -1;
fd_pos.x = -1;
fd_pos.y = -1;
}
else if (fd_pos.enterfrom >= 0 && fd_end.x == fd_pos.x && fd_pos.y == fd_end.y && fd_pos.enterfrom == fd_end.enterfrom) {
// destination found
printf ("%s:%d destination found fd_pos (%d,%d) fd_end (%d,%d)\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_end.x, fd_end.y);
fd_pos.enterfrom = -1;
fd_pos.x = -1;
fd_pos.y = -1;
}
else if (fd_pos.enterfrom >= 0 && fd_start.x == fd_pos.x && fd_start.y == fd_pos.y && fd_start.enterfrom == fd_pos.enterfrom) {
// start found
printf ("%s:%d start found fd_pos (%d,%d) fd_start (%d,%d)\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_start.x, fd_start.y);
fd_pos.enterfrom = -1;
fd_pos.x = -1;
fd_pos.y = -1;
}
else if (fd_data[GetRIdx(fd_pos.x, fd_pos.y)].e & (1 << fd_pos.enterfrom)) {
// old entry found
printf ("old entry found (%d,%d)\n", fd_pos.x, fd_pos.y);
fd_pos.enterfrom = -1;
fd_pos.x = -1;
fd_pos.y = -1;
}
else if (fd_pos.enterfrom >= 0) {
rpos = &railways[GetRIdx(fd_pos.x, fd_pos.y)];
fd_data[GetRIdx(fd_pos.x, fd_pos.y)].e |= (1 << fd_pos.enterfrom);
if (rpos->type == RAILWAY_NORMAL || rpos->type == RAILWAY_SENSOR) {
fd_pos = NextPos(fd_pos, rpos->dir);
fd_pos.parma++;
}
else if (rpos->type == RAILWAY_TURNOUT) {
fd_tmp = NextPos(fd_pos, rpos->altdir);
printf ("%s:%d turnout dir:%d altdir:%d fd_pos (%d,%d -> %d) fd_tmp (%d,%d -> %d)\n", __FILE__, __LINE__, rpos->dir, rpos->altdir, fd_pos.x, fd_pos.y, fd_pos.enterfrom, fd_tmp.x, fd_tmp.y, fd_tmp.enterfrom);
fd_tmp.parma++;
fd_list.push_back(fd_tmp);
fd_pos = NextPos(fd_pos, rpos->dir);
fd_pos.parma++;
printf ("%s:%d turnout fd_newpos (%d,%d -> %d)\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_pos.enterfrom);
}
else if (rpos->type == RAILWAY_CONNECTOR) {
int found = 0;
printf ("%s:%d connector found Reference:'%s'\n", __FILE__, __LINE__, rpos->name);
while (found == 0 && _FindReference(&x, &y, rpos->name) == 1) {
if (fd_pos.x != x || fd_pos.y != y) {
printf ("%s:%d found %d,%d\n", __FILE__, __LINE__, x, y);
fd_pos.x = x;
fd_pos.y = y;
rpos = &railways[GetRIdx(fd_pos.x, fd_pos.y)];
fd_pos = NextPos(fd_pos, rpos->dir);
fd_pos.parma++;
found = 1;
break;
}
}
if (found == 0) {
fd_pos.enterfrom = -1;
fd_pos.x = -1;
fd_pos.y = -1;
}
}
//
// if block is off ignore it completly
else if (rpos->type == RAILWAY_BLOCK) {
printf ("%s:%d block found\n", __FILE__, __LINE__);
if (server->blocks.IsOff(rpos->name)) {
printf ("%s:%d block is off\n", __FILE__, __LINE__);
fd_pos.enterfrom = -1;
fd_pos.x = -1;
fd_pos.y = -1;
}
else {
// lockedby = server->blocks.GetLockedby(rpos->name);
fd_pos = NextPos(fd_pos, rpos->dir);
fd_pos.parma++;
}
}
else { // finished
printf ("%s:%d finished?\n", __FILE__, __LINE__);
fd_pos.enterfrom = -1;
fd_pos.x = -1;
fd_pos.y = -1;
}
}
printf ("%s:%d fd_pos (%d,%d) enterfrom:%d\n\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_pos.enterfrom);
}
if (found == 0) *next = "";
UnLock();
free (fd_data);
return found;
};

@ -40,7 +40,20 @@ enum {
// | | | /| |\ | | |
// +---+ +---+ +---+ +---+
//
// Enter from
// 0
// +---+
// | |
// 3| |1
// | |
// +---+
// 2
enum {
EF_NORTH = 0,
EF_EAST,
EF_SOUTH,
EF_WEST
};
struct s_Railway {
int type;
@ -54,6 +67,17 @@ struct s_Railway {
char lockedby[REFERENCENAME_LEN]; // element locked by locreference (only set by server, not by JSON/Webinterface)
} typedef Railway;
struct s_findway_data {
int x;
int y;
int enterfrom; // enter field from clock view (0 = North, 3 = East... 6 ... 9)
int parma;
};
struct s_findway_map {
int e; // save entryfrom as (1 << entryfrom)
int score;
};
class Railways {
private:
@ -70,6 +94,8 @@ class Railways {
int GetRIdx(int x, int y);
JSONParse _GetJSONRailway(int x, int y);
void _New (int w, int h);
void DebugPrintFindWay(struct s_findway_map *fw);
int _FindReference(int *x, int *y, string name);
public:
Railways();
@ -97,6 +123,8 @@ class Railways {
int FindReference(int *x, int *y, string name);
int FindWay(string blockstart, string blockend, string lockedfor, string *next);
struct s_findway_data NextPos(struct s_findway_data pos, int dirtype);
};
#endif

@ -105,7 +105,7 @@ void Server::ThreadProcess() {
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);
if (i < 25 && 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;

@ -90,6 +90,7 @@ private:
friend class Sensors;
friend class Turnouts;
friend class Blocks;
friend class Railways;
public:
/////////////////////////////////////////
// functions here are required to be thread save

Loading…
Cancel
Save