working on short trains and split blocks

master
Steffen Pohle 2 years ago
parent 1018ec5990
commit 0845f417d2

@ -729,29 +729,326 @@ void::Locomotives::SendUpdate (Locomotive *loc) {
} }
int Locomotives::Loop() { /*
int lnum; * locomotive searching for a new way
* loco->way and loco->blocknext will be overwritten
* loco->way must be saved to loco->wayold before calling this function
* it will not set the auto_onroute step
*/
int Locomotives::Loco_SearchAndLock(Locomotive *loco) {
string way; string way;
Locomotive *loco = NULL;
//
// try to find and prepare(lock) a new way.
// nothing found check if we can reverse direction, this will be done only
// once a second (LOCO_TO_TRYAGAIN)
//
// destination empty? true -> random
// false -> find way to destination
if (loco->auto_timenext.tv_sec == 0 || timer_get(&loco->auto_timenext) > LOCO_TO_TRYAGAIN) {
debug (0, "Locomotives::Loop Search '%s' Reverse:%d", loco->name, loco->flags && LOCO_F_REVERSE ? 1 : 0);
timer_start(&loco->auto_timenext);
//
// destination set? - need to find a random block?
if (loco->blockdest[0] == 0) {
if (loco->flags & LOCO_F_RANDOM) {
if (server->railways.FindRandomWay(loco->blockassign, loco->name, &way)) {
size_t pos, pos1;
if ((pos = way.find(",b:", 1)) != string::npos) {
if ((pos1 = way.find(",", pos+3)) != string::npos) {
strncpy (loco->blocknext, way.substr(pos+3, pos1-(pos+3)).c_str(), REFERENCENAME_LEN);
}
else strncpy (loco->blocknext, way.substr(pos+3,string::npos).c_str(), REFERENCENAME_LEN);
strncpy (loco->auto_way, way.c_str(), WAYDATA_LEN);
if (server->railways.LockWay(way, loco->name) == 1) {
loco->auto_data = -1;
return 1;
}
server->railways.UnLockWay(way, loco->name);
}
}
else {
// nothing found -> try reverse
if (loco->blockassign[0] != 0 && (loco->flags & LOCO_F_CANREVERSE)) {
debug (0, "* Loco_SearchAndLock Reverse Loco %s", loco->name);
if (loco->blockassign[0] == '-') loco->blockassign[0] = '+';
else if (loco->blockassign[0] == '+') loco->blockassign[0] = '-';
if (loco->flags & LOCO_F_REVERSE) loco->flags &= ~LOCO_F_REVERSE;
else loco->flags |= LOCO_F_REVERSE;
}
}
}
else {
SchedulerNextStep(loco);
}
}
//
// we assume a destination is set, and try to find a new way to the destination
else if (server->railways.FindWay(loco->blockassign, loco->blockdest, loco->name, &way)) {
// try to lock way.
size_t pos, pos1;
debug (0, "Locomotives::Loop %s:%d Found Way:%s", __FILE__, __LINE__, way.c_str());
if ((pos = way.find(",b:", 1)) != string::npos) {
if ((pos1 = way.find(",", pos+3)) != string::npos) {
strncpy (loco->blocknext, way.substr(pos+3, pos1-(pos+3)).c_str(), REFERENCENAME_LEN);
}
else strncpy (loco->blocknext, way.substr(pos+3,string::npos).c_str(), REFERENCENAME_LEN);
strncpy (loco->auto_way, way.c_str(), WAYDATA_LEN);
if (server->railways.LockWay(way, loco->name) == 1) {
loco->auto_data = -1;
return 1;
}
server->railways.UnLockWay(way, loco->name);
timer_start(&loco->auto_timenext);
}
}
}
return 0;
}
/*
* prepare to lock the way set up in way
* the way is set and locked already, The turnouts will be set one by one with a time delay
* between the commands. All turnouts will get a SetWay command in case some turnout was set
* manualy without feedback to the server.
*/
int Locomotives::Loco_PrepareWay(Locomotive *loco) {
string block;
block = ((string)(loco->blocknext+2)).substr(0, ((string)(loco->blocknext+2)).find(","));
if (loco->auto_timenext.tv_sec == 0 || timer_get(&loco->auto_timenext) > LOCO_TO_TURNOUT) {
if (AutoCheckWaySingleStep(loco->auto_way, loco->name, &loco->auto_data) == 1) {
if ((loco->flags & LOCO_F_CARGO) ||
(server->blocks.GetFlags(block) & BLOCK_F_SPEEDLIMIT)) return 1;
else return 2;
}
timer_start(&loco->auto_timenext);
}
return 0;
}
/*
* loco is on route, check if entered a block
* returns if we entered the block, set the locos speed
* search for next way and set auto_onroute to LOCO_OR_ENTERBLOCKNEXT or ENTERBLOCKSTOP
* copy way to wayold. If a new way is found set the way if not leave empty
*/
int Locomotives::Loco_OnRoute(Locomotive *loco) {
string block;
string s_enter;
string s_slow;
string s_stop;
string s_shortstop;
int dir_reverse = 0;
char *tmpc = NULL;
string way;
// FIXME: move this code to the block class -> we will need a better code for multiple sensors
//
// the train is on the way, check for entering the block.
//
block = ((string)(loco->blocknext+2)).substr(0, ((string)(loco->blocknext+2)).find(","));
if (loco->blocknext[0] == '-') dir_reverse = 1;
else dir_reverse = 0;
s_shortstop = server->blocks.GetSensorShortStop(dir_reverse, block);
s_stop = server->blocks.GetSensorStop(dir_reverse, block);
s_slow = server->blocks.GetSensorSlow(dir_reverse, block);
s_enter = server->blocks.GetSensorEnter(dir_reverse, block);
if ( server->sensors.GetActive(s_enter) == 1 || server->sensors.GetActive(s_stop) == 1 ||
server->sensors.GetActive(s_slow) == 1 || server->sensors.GetActive(s_shortstop) == 1) { // entering block?
debug (0, "* Locomotive '%s' EnterBlock '%s'", loco->name, loco->blocknext);
debug (0, "* %s,%d Sensor Enter '%s' = %d", __FILE__, __LINE__, s_enter.c_str(), server->sensors.GetActive(s_enter));
debug (0, "* %s,%d Sensor Slow '%s' = %d", __FILE__, __LINE__, s_slow.c_str(), server->sensors.GetActive(s_slow));
debug (0, "* %s,%d Sensor Sh.Stop '%s' = %d", __FILE__, __LINE__, s_shortstop.c_str(), server->sensors.GetActive(s_shortstop));
debug (0, "* %s,%d Sensor Stop '%s' = %d", __FILE__, __LINE__, s_stop.c_str(), server->sensors.GetActive(s_stop));
// assignment <-- next, the assignment has to be checked
// against long trains and split blocks
// check if we need to clear dest
strncpy (loco->blockprev, loco->blockassign, REFERENCENAME_LEN);
tmpc = strstr (loco->blocknext, ",b:");
if (tmpc) {
strncpy (loco->blockassign, tmpc+3, REFERENCENAME_LEN);
strncpy (loco->blockassignsplit, loco->blocknext, REFERENCENAME_LEN);
}
else {
strncpy (loco->blockassign, loco->blocknext, REFERENCENAME_LEN);
loco->blockassignsplit[0] = 0;
}
strncpy (loco->auto_wayold, loco->auto_way, WAYDATA_LEN);
loco->auto_way[0] = 0;
loco->blocknext[0] = 0;
debug (0, "Locomotive::Loop Loco:'%s' Prev:'%s' Assign:'%s' AssignSplit:'%s' Next:'%s'",
loco->name, loco->blockprev, loco->blockassign, loco->blockassignsplit, loco->blocknext);
//
if (Loco_SearchAndLock(loco) == 1) {
loco->auto_onroute = LOCO_OR_ENTERBLOCKNEXT;
debug (0, "Locomotives::Loco_OnRoute Found Way Prepare '%s'\n", loco->name);
SetSpeed(loco->name, loco->vmid);
}
else {
loco->auto_onroute = LOCO_OR_ENTERBLOCKSTOP;
debug (0, "Locomotives::Loco_OnRoute Slow Down '%s'\n", loco->name);
SetSpeed(loco->name, loco->vslow);
}
return 1;
}
return 0;
}
/*
* loco entered a block, check if need to stop
*/
int Locomotives::Loco_BlockEnterStop(Locomotive *loco) {
string block;
string s_enter;
string s_slow;
string s_stop;
string s_shortstop;
int dir_reverse = 0;
string way;
//
// check if the train is in its stop position
//
block = ((string)(loco->blocknext+2)).substr(0, ((string)(loco->blocknext+2)).find(","));
if (loco->blockassign[0] == '-') dir_reverse = 1;
else dir_reverse = 0;
s_shortstop = server->blocks.GetSensorShortStop(dir_reverse, block);
s_stop = server->blocks.GetSensorStop(dir_reverse, block);
s_slow = server->blocks.GetSensorSlow(dir_reverse, block);
s_enter = server->blocks.GetSensorEnter(dir_reverse, block);
if ( server->sensors.GetActive(s_stop) == 1 ||
((loco->flags & LOCO_F_SHORTTRAIN) && server->sensors.GetActive(s_shortstop) == 1)) {
debug (0, "Locomotives::Loop EnterBlockStop '%s' UnLockWay\n", loco->name);
SetSpeed(loco->name, 0);
loco->auto_onroute = LOCO_OR_STOPWAIT;
server->railways.UnLockWay(loco->auto_wayold, loco->name);
server->blocks.SetLockedby(loco->blockprev+2, loco->name, 0);
loco->auto_wayold[0] = 0;
timer_start(&loco->auto_timenext);
}
return 0;
}
/*
* loco entered a block, check if need to stop
*/
int Locomotives::Loco_BlockEnterNext(Locomotive *loco) {
int dir_reverse;
string block; string block;
string s_enter; string s_enter;
string s_slow; string s_slow;
string s_stop; string s_stop;
string s_shortstop; string s_shortstop;
string way;
//
// check if the train is in its stop position
//
block = ((string)(loco->blockassign+2)).substr(0, ((string)(loco->blockassign+2)).find(","));
if (loco->blockassign[0] == '-') dir_reverse = 1;
else dir_reverse = 0;
s_shortstop = server->blocks.GetSensorShortStop(dir_reverse, block);
s_stop = server->blocks.GetSensorStop(dir_reverse, block);
s_slow = server->blocks.GetSensorSlow(dir_reverse, block);
s_enter = server->blocks.GetSensorEnter(dir_reverse, block);
if ( server->sensors.GetActive(s_stop) == 1 ||
((loco->flags & LOCO_F_SHORTTRAIN) && server->sensors.GetActive(s_shortstop) == 1)) {
if (loco->auto_timenext.tv_sec > 0) {
//
// end of block and not finished preparing the way.
// stop everything
debug (0, "Locomotives::Loco_BlockEnterNext ********** Loco:%s could not prepare way in time. STOP", loco->name);
server->PowerOnOff(0);
return 0;
}
else {
debug (0, "* Locomotives::Loco_BlockEnterNext endblock reached %s", loco->name);
server->railways.UnLockWay(loco->auto_wayold, loco->name);
server->blocks.SetLockedby(loco->blockprev+2, loco->name, 0);
loco->auto_wayold[0] = 0;
if ((loco->flags & LOCO_F_CARGO) ||
(server->blocks.GetFlags(block) & BLOCK_F_SPEEDLIMIT)) return 1;
else return 2;
}
}
if (loco->auto_timenext.tv_sec > 0 && timer_get(&loco->auto_timenext) > LOCO_TO_TURNOUT) {
debug (0, "* Locomotives::Loco_BlockEnterNext prepare way for loco: %s", loco->name);
if (AutoCheckWaySingleStep(loco->auto_way, loco->name, &loco->auto_data) == 1) {
//
// finished preparing new way, need to stay in ENTERBLOCKNEXT to unlock old way
debug (0, "* Locomotives::Loco_BlockEnterNext finished preparing way for loco: %s", loco->name);
loco->auto_timenext.tv_sec = 0;
}
else timer_start(&loco->auto_timenext);
}
return 0;
}
/*
* loco stopped on block, wait some time and continue with the next destination
*/
int Locomotives::Loco_BlockStopWait(Locomotive *loco) {
if (loco->auto_timenext.tv_sec == 0 || timer_get(&loco->auto_timenext) > 5000) {
if (loco->blockdest[0] != 0) loco->auto_onroute = LOCO_OR_SEARCH;
else loco->auto_onroute = LOCO_OR_NOTHING;
}
return 1;
}
int Locomotives::Loop() {
int lnum;
string way;
Locomotive *loco = NULL;
JSONParse jp; JSONParse jp;
int reverse = 1; int reverse = 1;
int dir_reverse = 0;
for (lnum = 0; lnum < max; lnum++) if (locomotives[lnum].name[0] != 0) { for (lnum = 0; lnum < max; lnum++) if (locomotives[lnum].name[0] != 0) {
loco = &locomotives[lnum]; loco = &locomotives[lnum];
if (loco->flags & LOCO_F_REVERSE) reverse = -1;
else reverse = 1;
if (loco->flags & LOCO_F_AUTO) { if (loco->flags & LOCO_F_AUTO) {
// //
// only in automate do anything alone // only in automate do anything alone
// //
debug (0, "* Locomotives::Loop (%s:%d) Loco:%s auto_onroute:%d assign:'%s' assignsplit:'%s' next:'%s' prev:'%s' dest:'%s' way:'%s' wayold:'%s'"
, __FILE__, __LINE__, loco->name, loco->auto_onroute, loco->blockassign, loco->blockassignsplit
, loco->blocknext, loco->blockprev, loco->blockdest, loco->auto_way, loco->auto_wayold);
if (loco->blockassign[0] == 0) { if (loco->blockassign[0] == 0) {
debug (0, "%s:%d Locomotive [%s] not assigned to any block. Set Mode to Man", __FILE__, __LINE__, loco->name); debug (0, "%s:%d Locomotive [%s] not assigned to any block. Set Mode to Man", __FILE__, __LINE__, loco->name);
SetModeMan(loco->name); SetModeMan(loco->name);
@ -759,8 +1056,7 @@ int Locomotives::Loop() {
} }
if (loco->auto_onroute == LOCO_OR_NOTHING) { if (loco->auto_onroute == LOCO_OR_NOTHING) {
// // loco mode is set to autostop -> set loco to man
// check if the loco mode is set to autostop
if (loco->flags & LOCO_F_AUTOSTOP) { if (loco->flags & LOCO_F_AUTOSTOP) {
SetModeMan(loco->name); SetModeMan(loco->name);
continue; continue;
@ -771,307 +1067,88 @@ int Locomotives::Loop() {
} }
} }
//
//
else if (loco->auto_onroute == LOCO_OR_SEARCH) { else if (loco->auto_onroute == LOCO_OR_SEARCH) {
// // loco mode is set to autostop -> set loco to man
// check if the loco mode is set to autostop
if (loco->flags & LOCO_F_AUTOSTOP) { if (loco->flags & LOCO_F_AUTOSTOP) {
SetModeMan(loco->name); SetModeMan(loco->name);
continue; continue;
} }
// // try to find and lock a way
// try to find and prepare(lock) a new way. if (Loco_SearchAndLock(loco)) {
// nothing found check if we can reverse direction, this will be done only loco->auto_onroute = LOCO_OR_PREPARE;
// once a second (LOCO_TO_TRYAGAIN)
//
// destination empty? true -> random
// false -> find way to destination
if (loco->auto_timenext.tv_sec == 0 || timer_get(&loco->auto_timenext) > LOCO_TO_TRYAGAIN) {
debug (0, "Locomotives::Loop Search '%s' Reverse:%d", loco->name, reverse);
timer_start(&loco->auto_timenext);
//
// destination set? - need to find a random block?
if (loco->blockdest[0] == 0) {
if (loco->flags & LOCO_F_RANDOM) {
if (server->railways.FindRandomWay(loco->blockassign, loco->name, &way)) {
size_t pos;
if ((pos = way.find(",b:", 1)) != string::npos) {
strncpy (loco->blocknext, way.substr(pos+3,string::npos).c_str(), REFERENCENAME_LEN);
strncpy (loco->auto_way, way.c_str(), WAYDATA_LEN);
if (server->railways.LockWay(way, loco->name) == 1) {
loco->auto_data = -1;
loco->auto_onroute = LOCO_OR_PREPARE;
}
else {
server->railways.UnLockWay(way, loco->name);
}
}
}
else {
// nothing found -> try reverse
if (loco->blockassign[0] != 0 && (loco->flags & LOCO_F_CANREVERSE)) {
debug (0, "* Reverse Loco %s", loco->name);
if (loco->blockassign[0] == '-') loco->blockassign[0] = '+';
else if (loco->blockassign[0] == '+') loco->blockassign[0] = '-';
if (loco->flags & LOCO_F_REVERSE) loco->flags &= ~LOCO_F_REVERSE;
else loco->flags |= LOCO_F_REVERSE;
}
}
}
else {
SchedulerNextStep(loco);
}
}
//
// we assume a destination is set, and try to find a new way to the destination
else if (server->railways.FindWay(loco->blockassign, loco->blockdest, loco->name, &way)) {
// try to lock way.
size_t pos;
debug (0, "Locomotives::Loop %s:%d Found Way:%s", __FILE__, __LINE__, way.c_str());
if ((pos = way.find(",b:", 1)) != string::npos) {
strncpy (loco->blocknext, way.substr(pos+3,string::npos).c_str(), REFERENCENAME_LEN);
strncpy (loco->auto_way, way.c_str(), WAYDATA_LEN);
if (server->railways.LockWay(way, loco->name) == 1) {
loco->auto_data = -1;
loco->auto_onroute = LOCO_OR_PREPARE;
}
else {
server->railways.UnLockWay(way, loco->name);
timer_start(&loco->auto_timenext);
}
}
}
else {
// no way found, can we reverse?
if (loco->blockassign[0] != 0 && (loco->flags & LOCO_F_CANREVERSE)) {
debug (0, "* Reverse Loco %s", loco->name);
if (loco->blockassign[0] == '-') loco->blockassign[0] = '+';
else if (loco->blockassign[0] == '+') loco->blockassign[0] = '-';
if (loco->flags & LOCO_F_REVERSE) loco->flags &= ~LOCO_F_REVERSE;
else loco->flags |= LOCO_F_REVERSE;
}
timer_start(&loco->auto_timenext);
}
} }
} }
//
//
else if (loco->auto_onroute == LOCO_OR_PREPARE) { else if (loco->auto_onroute == LOCO_OR_PREPARE) {
// switch (Loco_PrepareWay(loco)) {
// the way is set and locked already, The turnouts will be set one by one with a time delay case 1:
// between the commands. All turnouts will get a SetWay command in case some turnout was set SetSpeed(loco->name, reverse * loco->vmid);
// manualy without feedback to the server. loco->auto_onroute = LOCO_OR_ONTHEWAY;
// debug (0, "* Locomotive '%s' Way Prepared -> Speed: VMID", loco->name);
block = ((string)(loco->blocknext+2)).substr(0, ((string)(loco->blocknext+2)).find(",")); jp.Clear();
jp.AddObject("locomotive",_GetJSON(lnum));
if (loco->auto_timenext.tv_sec == 0 || timer_get(&loco->auto_timenext) > LOCO_TO_TURNOUT) { if(network) network->ChangeListPushToAll(jp.ToString());
if (AutoCheckWaySingleStep(loco->auto_way, loco->name, &loco->auto_data) == 1) { break;
// all turnouts are set, start the train. case 2:
debug (0, "* Locomotive '%s' Way Locked Start", loco->name); SetSpeed(loco->name, reverse * loco->vfast);
if ((loco->flags & LOCO_F_CARGO) || loco->auto_onroute = LOCO_OR_ONTHEWAY;
(server->blocks.GetFlags(block) & BLOCK_F_SPEEDLIMIT)) debug (0, "* Locomotive '%s' Way Prepared -> Speed: VFAST", loco->name);
SetSpeed(loco->name, reverse * loco->vmid); jp.Clear();
else SetSpeed(loco->name, reverse * loco->vfast); jp.AddObject("locomotive",_GetJSON(lnum));
loco->auto_onroute = LOCO_OR_ONTHEWAY; if(network) network->ChangeListPushToAll(jp.ToString());
} break;
else timer_start(&loco->auto_timenext); default:
break;
} }
} }
else if (loco->auto_onroute == LOCO_OR_ONTHEWAY) { else if (loco->auto_onroute == LOCO_OR_ONTHEWAY) {
// FIXME: move this code to the block class -> we will need a better code for multiple sensors if (Loco_OnRoute(loco)) {
//
// the train is on the way, check for entering the block.
//
block = ((string)(loco->blocknext+2)).substr(0, ((string)(loco->blocknext+2)).find(","));
if (loco->blocknext[0] == '-') dir_reverse = 1;
else dir_reverse = 0;
s_shortstop = server->blocks.GetSensorShortStop(dir_reverse, block);
s_stop = server->blocks.GetSensorStop(dir_reverse, block);
s_slow = server->blocks.GetSensorSlow(dir_reverse, block);
s_enter = server->blocks.GetSensorEnter(dir_reverse, block);
if ( server->sensors.GetActive(s_enter) == 1 || server->sensors.GetActive(s_stop) == 1 ||
server->sensors.GetActive(s_slow) == 1 || server->sensors.GetActive(s_shortstop) == 1) { // entering block?
debug (0, "* Locomotive '%s' EnterBlock '%s'", loco->name, loco->blocknext);
debug (0, "* %s,%d Sensor Enter '%s' = %d", __FILE__, __LINE__, s_enter.c_str(), server->sensors.GetActive(s_enter));
debug (0, "* %s,%d Sensor Slow '%s' = %d", __FILE__, __LINE__, s_slow.c_str(), server->sensors.GetActive(s_slow));
debug (0, "* %s,%d Sensor Sh.Stop '%s' = %d", __FILE__, __LINE__, s_shortstop.c_str(), server->sensors.GetActive(s_shortstop));
debug (0, "* %s,%d Sensor Stop '%s' = %d", __FILE__, __LINE__, s_stop.c_str(), server->sensors.GetActive(s_stop));
// unlock old assigned block
if (loco->blockassign[0] != 0) server->blocks.SetLockedby((string)(loco->blockassign+2), loco->name, 0);
// assignment <-- next
// check if we need to clear dest
strncpy (loco->blockprev, loco->blockassign, REFERENCENAME_LEN);
strncpy (loco->blockassign, loco->blocknext, REFERENCENAME_LEN);
strncpy (loco->auto_wayold, loco->auto_way, WAYDATA_LEN);
loco->auto_way[0] = 0;
loco->blocknext[0] = 0;
//
// if destination reached or AUTO-MAN mode: stop train.
if ((strncmp(loco->blockassign, loco->blockdest, REFERENCENAME_LEN) == 0)
|| (loco->flags & LOCO_F_AUTOSTOP)) {
printf ("%s:%d LOCO_OR_ONTHEWAY enter assign == dest stop train\n", __FILE__, __LINE__);
loco->blockdest[0] = 0;
loco->auto_onroute = LOCO_OR_ENTERBLOCKSTOP;
SetSpeed(loco->name, reverse * loco->vslow);
}
//
// if not try to find next block.
else {
printf ("%s:%d LOCO_OR_ONTHEWAY try to find new way\n", __FILE__, __LINE__);
if (loco->blockdest[0] == 0) {
if ((loco->flags & LOCO_F_RANDOM) && ((loco->flags & LOCO_F_CARGO) || !(server->blocks.GetFlags(block) & BLOCK_F_STATION)))
if (server->railways.FindRandomWay(loco->blockassign, loco->name, &way)) {
size_t pos;
if ((pos = way.find(",b:", 1)) != string::npos) {
strncpy (loco->blocknext, way.substr(pos+3,string::npos).c_str(), REFERENCENAME_LEN);
strncpy (loco->auto_way, way.c_str(), WAYDATA_LEN);
if (server->railways.LockWay(way, loco->name) == 1) {
loco->auto_data = -1;
loco->auto_onroute = LOCO_OR_ENTERBLOCKNEXT;
}
else {
server->railways.UnLockWay(way, loco->name);
timer_start(&loco->auto_timenext);
}
}
}
}
else if (server->railways.FindWay(loco->blockassign, loco->blockdest, loco->name, &way)) {
size_t pos;
if ((pos = way.find(",b:", 1)) != string::npos) {
strncpy (loco->blocknext, way.substr(pos+3,string::npos).c_str(), REFERENCENAME_LEN);
strncpy (loco->auto_way, way.c_str(), WAYDATA_LEN);
if (server->railways.LockWay(way, loco->name) == 1) {
loco->auto_data = -1;
loco->auto_onroute = LOCO_OR_ENTERBLOCKNEXT;
}
else {
loco->auto_onroute = LOCO_OR_ENTERBLOCKSTOP;
SetSpeed(loco->name, reverse * loco->vslow);
}
}
else {
loco->auto_onroute = LOCO_OR_ENTERBLOCKSTOP;
SetSpeed(loco->name, reverse * loco->vslow);
}
}
else {
loco->auto_onroute = LOCO_OR_ENTERBLOCKSTOP;
SetSpeed(loco->name, reverse * loco->vslow);
}
}
jp.Clear(); jp.Clear();
jp.AddObject("locomotive",_GetJSON(lnum)); jp.AddObject("locomotive",_GetJSON(lnum));
if(network) network->ChangeListPushToAll(jp.ToString()); if(network) network->ChangeListPushToAll(jp.ToString());
if (loco->auto_onroute == LOCO_OR_ONTHEWAY) {
loco->auto_onroute = LOCO_OR_ENTERBLOCKSTOP;
SetSpeed(loco->name, reverse * loco->vslow);
}
} }
} }
else if (loco->auto_onroute == LOCO_OR_ENTERBLOCKSTOP) { else if (loco->auto_onroute == LOCO_OR_ENTERBLOCKSTOP) {
// if (Loco_BlockEnterStop(loco)) {
// check if the train is in its stop position
//
block = ((string)(loco->blocknext+2)).substr(0, ((string)(loco->blocknext+2)).find(","));
if (loco->blockassign[0] == '-') dir_reverse = 1;
else dir_reverse = 0;
s_shortstop = server->blocks.GetSensorShortStop(dir_reverse, block);
s_stop = server->blocks.GetSensorStop(dir_reverse, block);
s_slow = server->blocks.GetSensorSlow(dir_reverse, block);
s_enter = server->blocks.GetSensorEnter(dir_reverse, block);
if ( server->sensors.GetActive(s_stop) == 1 ||
((loco->flags & LOCO_F_SHORTTRAIN) && server->sensors.GetActive(s_shortstop) == 1)) {
debug (0, "Locomotives::Loop EnterBlockStop '%s' UnLockWay\n", loco->name);
SetSpeed(loco->name, 0);
loco->auto_onroute = LOCO_OR_STOPWAIT;
server->railways.UnLockWay(loco->auto_wayold, loco->name);
server->blocks.SetLockedby(loco->blockprev+2, loco->name, 0);
loco->auto_wayold[0] = 0;
jp.Clear(); jp.Clear();
jp.AddObject("locomotive",_GetJSON(lnum)); jp.AddObject("locomotive",_GetJSON(lnum));
if(network) network->ChangeListPushToAll(jp.ToString()); if(network) network->ChangeListPushToAll(jp.ToString());
timer_start(&loco->auto_timenext);
} }
} }
else if (loco->auto_onroute == LOCO_OR_ENTERBLOCKNEXT) { else if (loco->auto_onroute == LOCO_OR_ENTERBLOCKNEXT) {
// check enter block switch (Loco_BlockEnterNext(loco)) {
int finish = 0; case 1:
SetSpeed(loco->name, reverse * loco->vmid);
if (loco->auto_timenext.tv_sec == 0 || timer_get(&loco->auto_timenext) > LOCO_TO_TURNOUT) { loco->auto_onroute = LOCO_OR_ONTHEWAY;
if (AutoCheckWaySingleStep(loco->auto_way, loco->name, &loco->auto_data) == 1) debug (0, "* Locomotive LOCO_OR_ENTERBLOCKNEXT '%s' Way Prepared -> Speed: VMID", loco->name);
finish = 1; jp.Clear();
else jp.AddObject("locomotive",_GetJSON(lnum));
timer_start(&loco->auto_timenext); if(network) network->ChangeListPushToAll(jp.ToString());
} break;
case 2:
block = ((string)(loco->blocknext+2)).substr(0, ((string)(loco->blocknext+2)).find(",")); SetSpeed(loco->name, reverse * loco->vfast);
if (loco->blockassign[0] == '-') dir_reverse = 1; loco->auto_onroute = LOCO_OR_ONTHEWAY;
else dir_reverse = 0; debug (0, "* Locomotive LOCO_OR_ENTERBLOCKNEXT '%s' Way Prepared -> Speed: VFAST", loco->name);
jp.Clear();
s_shortstop = server->blocks.GetSensorShortStop(dir_reverse, block); jp.AddObject("locomotive",_GetJSON(lnum));
s_stop = server->blocks.GetSensorStop(dir_reverse, block); if(network) network->ChangeListPushToAll(jp.ToString());
s_slow = server->blocks.GetSensorSlow(dir_reverse, block); break;
s_enter = server->blocks.GetSensorEnter(dir_reverse, block); default:
break;
if ( server->sensors.GetActive(s_stop) == 1 ||
((loco->flags & LOCO_F_SHORTTRAIN) && server->sensors.GetActive(s_shortstop) == 1)) {
debug (0, "Locomotives::Loop EnterBlockNext Loco:'%s' Block: '%s' UnLockWay", loco->name, block.c_str());
debug (0, "* %s,%d Sensor Enter '%s' = %d", __FILE__, __LINE__, s_enter.c_str(), server->sensors.GetActive(s_enter));
debug (0, "* %s,%d Sensor Slow '%s' = %d", __FILE__, __LINE__, s_slow.c_str(), server->sensors.GetActive(s_slow));
debug (0, "* %s,%d Sensor Sh.Stop '%s' = %d", __FILE__, __LINE__, s_shortstop.c_str(), server->sensors.GetActive(s_shortstop));
debug (0, "* %s,%d Sensor Stop '%s' = %d", __FILE__, __LINE__, s_stop.c_str(), server->sensors.GetActive(s_stop));
server->railways.UnLockWay(loco->auto_wayold, loco->name);
server->blocks.SetLockedby(loco->blockprev+2, loco->name, 0);
loco->auto_wayold[0] = 0;
if (finish == 0) { // stop train if not finished
debug (0, "Locomotives::Loop '%s' UnLockWay\n", loco->name);
SetSpeed(loco->name, 0);
loco->auto_onroute = LOCO_OR_STOPWAIT;
jp.Clear();
jp.AddObject("locomotive",_GetJSON(lnum));
if(network) network->ChangeListPushToAll(jp.ToString());
timer_start(&loco->auto_timenext);
}
else {
if (server->blocks.GetFlags(block) & BLOCK_F_SPEEDLIMIT) {
SetSpeed(loco->name, reverse * loco->vmid);
}
loco->auto_onroute = LOCO_OR_ONTHEWAY;
}
} }
} }
else if (loco->auto_onroute == LOCO_OR_STOPWAIT) { else if (loco->auto_onroute == LOCO_OR_STOPWAIT) {
if (loco->auto_timenext.tv_sec == 0 || timer_get(&loco->auto_timenext) > 5000) { Loco_BlockStopWait(loco);
if (loco->blockdest[0] != 0) loco->auto_onroute = LOCO_OR_SEARCH;
else loco->auto_onroute = LOCO_OR_NOTHING;
}
} }
} }
} }
@ -1080,6 +1157,7 @@ int Locomotives::Loop() {
} }
int Locomotives::Test(string loco) { int Locomotives::Test(string loco) {
int res = 0; int res = 0;
int i; int i;

@ -56,6 +56,7 @@ struct s_Locomotive {
int speed; // current speed int speed; // current speed
int64_t func; // function enabled ... light... int64_t func; // function enabled ... light...
char blockassign[REFERENCENAME_LEN]; // currently assigned block [+BLOCKREFNAME ... -BLOCKREFNAME] char blockassign[REFERENCENAME_LEN]; // currently assigned block [+BLOCKREFNAME ... -BLOCKREFNAME]
char blockassignsplit[REFERENCENAME_LEN]; // if assigned block is a split block, save full way.
char blocknext[REFERENCENAME_LEN]; // next block to go to char blocknext[REFERENCENAME_LEN]; // next block to go to
char blockprev[REFERENCENAME_LEN]; // prev block (mostly assigned block char blockprev[REFERENCENAME_LEN]; // prev block (mostly assigned block
char blockdest[REFERENCENAME_LEN]; // destination block char blockdest[REFERENCENAME_LEN]; // destination block
@ -83,7 +84,12 @@ class Locomotives {
JSONParse _GetJSON(int idx); JSONParse _GetJSON(int idx);
int SchedulerNextStep(Locomotive *loc); // automode, calculate next step int SchedulerNextStep(Locomotive *loc); // automode, calculate next step
void SendUpdate(Locomotive *loc); void SendUpdate(Locomotive *loc);
int Loco_SearchAndLock(Locomotive *loco);
int Loco_PrepareWay(Locomotive *loco);
int Loco_OnRoute(Locomotive *loco);
int Loco_BlockEnterStop(Locomotive *loco);
int Loco_BlockEnterNext(Locomotive *loco);
int Loco_BlockStopWait(Locomotive *loco);
public: public:
Locomotives(); Locomotives();
~Locomotives(); ~Locomotives();

@ -512,8 +512,10 @@ string Railways::GetDestBlock(int locoflags, string blockend) {
block = blockend; block = blockend;
} }
debug (0, "Railway::GetDestBlock Final split:%d blockend:%s" debug (0, "Railway::GetDestBlock Final split:%d loco short:%d blockend:%s -> block:%s"
, (block_f & BLOCK_F_SPLIT) ? 1 : 0 , (block_f & BLOCK_F_SPLIT) ? 1 : 0
, (locoflags & LOCO_F_SHORTTRAIN) ? 1: 0
, blockend.c_str()
, block.c_str()); , block.c_str());
return block; return block;
@ -621,7 +623,7 @@ int Railways::FindWay(string org_blockstart, string org_blockend, string lockedf
// this will be done in respect of lockedby blocks and ways. // this will be done in respect of lockedby blocks and ways.
// //
while ((fd_list.size() > 0 || fd_pos.enterfrom >= 0) && found == 0) { while ((fd_list.size() > 0 || fd_pos.enterfrom >= 0) && found == 0) {
// DebugPrintFindWay(fd_data); // DebugPrintFindWay(fd_data);
if (fd_pos.enterfrom < 0) { if (fd_pos.enterfrom < 0) {
std::list<struct s_findway_data>::iterator iter; std::list<struct s_findway_data>::iterator iter;
@ -1102,6 +1104,7 @@ int Railways::FindRandomWay(string blockstart, string lockedfor, string *next) {
/* /*
* try to lock or unlock the way for the loco(lockedby) * try to lock or unlock the way for the loco(lockedby)
* this lock will only go from one to the next block.
* Will also do the check for long trains and split blocks. * Will also do the check for long trains and split blocks.
*/ */
int Railways::LockWay (string way, string lockedby, int lockonoff) { int Railways::LockWay (string way, string lockedby, int lockonoff) {
@ -1111,12 +1114,13 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) {
struct s_findway_data start; struct s_findway_data start;
struct s_findway_data end; struct s_findway_data end;
struct s_findway_data pos; struct s_findway_data pos;
string startblock, endblock, endblock2; string startblock, startblock2, endblock, endblock2;
Railway *r; Railway *r;
int finished = 0; int finished = 0;
JSONParse jp; JSONParse jp;
int locoflags = 0; int locoflags = 0;
int blockflags = 0; int blockendflags = 0;
int blockstartflags = 0;
debug (0, "* LockWay Way:'%s' for '%s' lockonoff:%d", way.c_str(), lockedby.c_str(), lockonoff); debug (0, "* LockWay Way:'%s' for '%s' lockonoff:%d", way.c_str(), lockedby.c_str(), lockonoff);
@ -1128,7 +1132,7 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) {
if ((pos2 = way.find(",", pos1+1)) == string::npos) return 0; if ((pos2 = way.find(",", pos1+1)) == string::npos) return 0;
startblock = way.substr (pos1+2, pos2-pos1-2); startblock = way.substr (pos1+2, pos2-pos1-2);
if ((pos1 = way.rfind(",b:")) == string::npos) return 0; if ((pos1 = way.find(",b:",pos2)) == string::npos) return 0;
if ((pos2 = way.find(",", pos1+1)) == string::npos) endblock = way.substr (pos1+3, pos2); if ((pos2 = way.find(",", pos1+1)) == string::npos) endblock = way.substr (pos1+3, pos2);
else endblock = way.substr (pos1+3, pos2-pos1-3); else endblock = way.substr (pos1+3, pos2-pos1-3);
@ -1136,13 +1140,16 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) {
// take care of split blocks and long trains. // take care of split blocks and long trains.
// if the second block is not needed endblock2 will remain empty // if the second block is not needed endblock2 will remain empty
locoflags = server->locomotives.GetFlags(lockedby); locoflags = server->locomotives.GetFlags(lockedby);
blockflags = server->blocks.GetFlags(endblock.substr(2, string::npos)); blockendflags = server->blocks.GetFlags(endblock.substr(2, string::npos));
if (!(locoflags & LOCO_F_SHORTTRAIN) && (blockflags & BLOCK_F_SPLIT)) if (!(locoflags & LOCO_F_SHORTTRAIN) && (blockendflags & BLOCK_F_SPLIT))
endblock2 = server->blocks.GetSecondBlock(endblock.substr(2, string::npos)); endblock2 = server->blocks.GetSecondBlock(endblock.substr(2, string::npos));
else endblock2 = ""; else endblock2 = "";
debug (0, "%s:%d LockWay Way: '%s' Startblock: '%s' Endblock: '%s' Endblock2: '%s'", __FILE__, __LINE__, way.c_str(), blockstartflags = server->blocks.GetFlags(startblock.substr(2, string::npos));
startblock.c_str(), endblock.c_str(), endblock2.c_str()); if (!(locoflags & LOCO_F_SHORTTRAIN) && (blockstartflags & BLOCK_F_SPLIT))
startblock2 = server->blocks.GetSecondBlock(startblock.substr(2, string::npos));
else startblock2 = "";
debug (0, "%s:%d LockWay Way: '%s' Startblock: '%s' Startblock2: '%s' Endblock: '%s' Endblock2: '%s'", __FILE__, __LINE__, way.c_str(),
startblock.c_str(), startblock2.c_str(), endblock.c_str(), endblock2.c_str());
// //
// find start position // find start position
@ -1181,7 +1188,7 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) {
return 0; return 0;
} }
printf ("%s:%d LockWay Way:'%s' start [%d,%d -> %d] to [%d,%d -> %d] LockenOnOff:%d\n", __FILE__, __LINE__, way.c_str(), printf ("%s:%d LockWay Way:'%s' start [%d,%d -> %d] to [%d,%d -> %d] LockOnOff:%d\n", __FILE__, __LINE__, way.c_str(),
start.x, start.y, start.enterfrom, end.x, end.y, end.enterfrom, lockonoff); start.x, start.y, start.enterfrom, end.x, end.y, end.enterfrom, lockonoff);
// //
@ -1198,7 +1205,7 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) {
finished = 0; finished = 0;
do { do {
r = &railways[GetRIdx(pos.x, pos.y)]; r = &railways[GetRIdx(pos.x, pos.y)];
printf ("LockWay Position [%d,%d] Name:%s LockedBy:'%s'\n", pos.x, pos.y, r->name, r->lockedby); debug (0, "LockWay Position [%d,%d] Name:%s LockedBy:'%s'", pos.x, pos.y, r->name, r->lockedby);
// check if railway is free or locked by me // check if railway is free or locked by me
if (r->lockedby[0] != 0 && lockedby.compare(r->lockedby) != 0 && !(lockonoff == 0 && pos.x == start.x && pos.y == start.y && r->type == RAILWAY_BLOCK)) { if (r->lockedby[0] != 0 && lockedby.compare(r->lockedby) != 0 && !(lockonoff == 0 && pos.x == start.x && pos.y == start.y && r->type == RAILWAY_BLOCK)) {
@ -1207,7 +1214,7 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) {
return 0; return 0;
} }
// do lock start and endpoint... unlock only start // lock start and endpoint... unlock only start
if ((pos.x == end.x && pos.y == end.y) || (r->type == RAILWAY_BLOCK && if ((pos.x == end.x && pos.y == end.y) || (r->type == RAILWAY_BLOCK &&
((endblock.compare(r->name) == 0) || ((endblock.compare(r->name) == 0) ||
(endblock2.length() > 0 && endblock2.compare(r->name) == 0)))) { (endblock2.length() > 0 && endblock2.compare(r->name) == 0)))) {
@ -1245,12 +1252,24 @@ int Railways::LockWay (string way, string lockedby, int lockonoff) {
break; break;
} }
if ((pos.x == end.x && pos.y == end.y) || //
(lockonoff == 0 && // to prevent unlocking split blocks on enter, check if the start and the end are different blocks.
((endblock.compare(r->name) == 0) || // ignore this if startblock and endblock are the same split block.
(endblock2.length() > 0 && endblock2.compare(r->name) == 0)))) { if (locoflags & LOCO_F_SHORTTRAIN) {
finished = 1; if (pos.x == end.x && pos.y == end.y) {
break; finished = 1;
break;
}
}
else {
// freeing way on stop: abort if block is part of the split endblock
if ((pos.x == end.x && pos.y == end.y) ||
(lockonoff == 0 && (endblock.compare(startblock.substr(0,2) + startblock2) != 0) &&
((endblock.compare(r->name) == 0) ||
(endblock2.length() > 0 && endblock2.compare(r->name) == 0)))) {
finished = 1;
break;
}
} }
// go to next position // go to next position

Loading…
Cancel
Save