#include "modelbahn.h" #include "locomotive.h" Locomotives::Locomotives () { changed = 0; locomotives = (Locomotive*) malloc(sizeof(Locomotive)*LOCOMOTIVES_MAX); memset(locomotives, 0x0, sizeof(Locomotive)*LOCOMOTIVES_MAX); max = SENSORS_MAX; }; Locomotives::~Locomotives() { free (locomotives); locomotives = NULL; max = 0; }; int Locomotives::Lock() { if (pthread_mutex_lock(&mtx) == 0) return 1; else return 0; } int Locomotives::UnLock() { if (pthread_mutex_unlock(&mtx) == 0) return 1; else return 0; } JSONParse Locomotives::_GetJSON(int idx) { JSONParse json; JSONElement je; string s = ""; json.Clear(); s = locomotives[idx].name; json.AddObject("name", s); s = locomotives[idx].ifname; json.AddObject("ifname", s); s = locomotives[idx].blockdest; json.AddObject("blockdest", s); s = locomotives[idx].blocknext; json.AddObject("blocknext", s); s = locomotives[idx].blockassign; json.AddObject("blockassign", s); s = locomotives[idx].blockprev; json.AddObject("blockprev", s); s = locomotives[idx].auto_way; json.AddObject("auto_way", s); s = locomotives[idx].auto_wayold; json.AddObject("auto_wayold", s); json.AddObject("addr", locomotives[idx].addr); json.AddObject("stepcode", locomotives[idx].stepcode); json.AddObject("speed", locomotives[idx].speed); json.AddObject("func", locomotives[idx].func); json.AddObject("flags", locomotives[idx].flags); json.AddObject("vmin", locomotives[idx].vmin); json.AddObject("vslow", locomotives[idx].vslow); json.AddObject("vmid", locomotives[idx].vmid); json.AddObject("vfast", locomotives[idx].vfast); json.AddObject("vmax", locomotives[idx].vmax); return json; }; JSONParse Locomotives::GetJSON(string name) { int i; JSONParse jp; jp.Clear(); Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) { if (name.compare(locomotives[i].name) == 0) { jp = _GetJSON(i); } } UnLock(); return jp; }; void Locomotives::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 = "locomotives"; for (cnt = 0, i = 0; i < max; i++) if (locomotives[i].name[0] != 0) { if (cnt != 0) je.value += ","; // not first element je.value += _GetJSON(i).ToString(); cnt++; } json->AddObject(je); UnLock(); }; Locomotive Locomotives::GetLocomotiveFromJSON(JSONParse *j) { Locomotive l; string s; l.name[0] = 0; l.ifname[0] = 0; l.addr = 0; l.stepcode = 0; l.vmin = 0; l.vslow = 0; l.vmid = 0; l.vfast = 0; l.vmax = 0; l.flags = 0; l.speed = 0; l.func = 0; l.blockassign[0] = 0; l.blockdest[0] = 0; l.blocknext[0] = 0; l.blockprev[0] = 0; l.auto_way[0] = 0; l.auto_wayold[0] = 0; l.auto_onroute = 0; l.auto_data = 0; l.auto_timenext = {0}; j->GetValue("name", &s); strncpy (l.name, s.c_str(), REFERENCENAME_LEN); j->GetValue("ifname", &s); strncpy (l.ifname, s.c_str(), REFERENCENAME_LEN); j->GetValue("blockassign", &s); strncpy (l.blockassign, s.c_str(), REFERENCENAME_LEN); j->GetValue("blockdest", &s); strncpy (l.blockdest, s.c_str(), REFERENCENAME_LEN); j->GetValue("blockprev", &s); strncpy (l.blockprev, s.c_str(), REFERENCENAME_LEN); j->GetValue("blocknext", &s); strncpy (l.blocknext, s.c_str(), REFERENCENAME_LEN); j->GetValueInt("addr", &l.addr); j->GetValueInt("stepcode", &l.stepcode); j->GetValueInt("speed", &l.speed); j->GetValueInt64("func", &l.func); j->GetValueInt("flags", &l.flags); j->GetValueInt("vmin", &l.vmin); j->GetValueInt("vslow", &l.vslow); j->GetValueInt("vmid", &l.vmid); j->GetValueInt("vfast", &l.vfast); j->GetValueInt("vmax", &l.vmax); return l; }; int Locomotives::Change(Locomotive *loco) { int i; int ifree = -1; Lock(); for (i = 0; i < max; i++) { if (locomotives[i].name[0] != 0) { // found element if (strncmp(locomotives[i].name, loco->name, REFERENCENAME_LEN) == 0) { // copy block data strncpy (locomotives[i].ifname, loco->name, REFERENCENAME_LEN); locomotives[i].addr = loco->addr; locomotives[i].stepcode = loco->stepcode; locomotives[i].vmin = loco->vmin; locomotives[i].vslow = loco->vslow; locomotives[i].vmid = loco->vmid; locomotives[i].vfast = loco->vfast; locomotives[i].vmax = loco->vmax; locomotives[i].flags = loco->flags; // locomotives[i].speed = 0; // locomotives[i].func = 0; ifree = i; break; } } else if (ifree == -1) ifree = i; } // element not found add new element if (ifree != -1 && ifree < max) { locomotives[ifree] = *loco; strncpy (locomotives[ifree].name, loco->name, REFERENCENAME_LEN); strncpy (locomotives[ifree].ifname, loco->ifname, REFERENCENAME_LEN); } changed = 1; UnLock(); return 1; }; int Locomotives::Delete(string name) { int i; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) { if (name.compare(locomotives[i].name) == 0) { locomotives[i].name[0] = 0; locomotives[i].ifname[0] = 0; locomotives[i].addr = 0; locomotives[i].stepcode = 0; locomotives[i].vmin = 0; locomotives[i].vslow = 0; locomotives[i].vmid = 0; locomotives[i].vfast = 0; locomotives[i].vmax = 0; locomotives[i].flags = 0; locomotives[i].auto_way[0] = 0; locomotives[i].auto_wayold[0] = 0; locomotives[i].auto_onroute = -1; locomotives[i].auto_data = -1; locomotives[i].auto_timenext = {0}; changed = 1; break; } } UnLock(); return 1; }; int Locomotives::SetSpeed(string name, int speed) { int i; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) { if (name.compare(locomotives[i].name) == 0) { server->interfaces.SetLocoSpeed(&locomotives[i], speed); break; } } UnLock(); return 1; }; int Locomotives::SetReverse(string name, int reverse) { int i; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) { if (name.compare(locomotives[i].name) == 0) { if (reverse) locomotives[i].flags |= LOCO_F_REVERSE; else locomotives[i].flags &= ~LOCO_F_REVERSE; server->interfaces.SetLocoSpeed(&locomotives[i], locomotives[i].speed); break; } } UnLock(); return 1; }; int Locomotives::SetFunction(string name, int func, int value) { int i; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) { if (name.compare(locomotives[i].name) == 0) { server->interfaces.SetLocoFunction(&locomotives[i], func, value); break; } } UnLock(); return 1; }; int Locomotives::SetDestination (string name, string block, int direction) { int i; string way; int blflags; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) if (name.compare(locomotives[i].name) == 0) { debug (0, "Locomotives::SetDestination (Name:%s Block:%s Direction:%d)", name.c_str(), block.c_str(), direction); blflags = server->blocks.GetFlags(block); if ((blflags & BLOCK_F_SHORT) && !(locomotives[i].flags & LOCO_F_SHORTTRAIN)) break; if ((blflags & BLOCK_F_ENDSTATION) && !(locomotives[i].flags & LOCO_F_CANREVERSE)) break; if (direction) snprintf (locomotives[i].blockdest, REFERENCENAME_LEN, "-:%s", block.c_str()); else snprintf (locomotives[i].blockdest, REFERENCENAME_LEN, "+:%s", block.c_str()); break; } UnLock(); return 1; } int Locomotives::SetAssign (string name, string block, int direction) { int i, x = -1; int y = -1; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) if (name.compare(locomotives[i].name) == 0) { debug (0, "Locomotives::SetAssign (Name:%s Block:%s Direction:%d)", name.c_str(), block.c_str(), direction); if (locomotives[i].flags & LOCO_F_AUTO) { debug (0, "Locomotives::SetAssign not possible Loco is stil in AUTO mode."); i = max; continue; } if (locomotives[i].blockassign[0] != 0) // still locked unlock server->blocks.SetLockedby(locomotives[i].blockassign+2, name, 0); if (direction) snprintf (locomotives[i].blockassign, REFERENCENAME_LEN, "-:%s", block.c_str()); else snprintf (locomotives[i].blockassign, REFERENCENAME_LEN, "+:%s", block.c_str()); server->blocks.SetLockedby(block, name, 1); break; } UnLock(); if (i < max && i >=0) { while (server->railways.FindReference(&x, &y, block)) { string bl = server->blocks.GetLockedby(block); if(bl.length() == 0 || bl.compare(name) == 0) { server->blocks.SetLockedby(block, name, 1); server->railways.SetLockedby(x, y, name, 1); } } } printf ("%s:%d %s ************** finish me **************\n", __FILE__, __LINE__, __FUNCTION__); printf ("%s:%d %s * clear old refferences from loco \n", __FILE__, __LINE__, __FUNCTION__); printf ("%s:%d %s * stop loco \n", __FILE__, __LINE__, __FUNCTION__); return 1; } int Locomotives::GetFlags(string name) { int flags = -1; int i; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) if (name.compare(locomotives[i].name) == 0) { flags = locomotives[i].flags; } UnLock(); return flags; } int Locomotives::Reset(string name) { Railway rw; int i; JSONParse jp; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) if (name.compare(locomotives[i].name) == 0) { debug (0, "Locomotives::Reset (Name:%s)", name.c_str()); locomotives[i].blockassign[0] = 0; locomotives[i].blockdest[0] = 0; locomotives[i].blockprev[0] = 0; locomotives[i].blocknext[0] = 0; locomotives[i].auto_way[0] = 0; locomotives[i].auto_wayold[0] = 0; locomotives[i].auto_onroute = -1; break; } server->railways.ClearLockedby(name); server->blocks.ClearLockedby(name); jp.AddObject("locomotive",_GetJSON(i)); if(network) network->ChangeListPushToAll(jp.ToString()); UnLock(); return 1; }; int Locomotives::SetMan(string name) { int i; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) if (name.compare(locomotives[i].name) == 0) { debug (0, "Locomotives::SetMan (Name:%s)\n", name.c_str()); locomotives[i].flags &= ~(LOCO_F_AUTO | LOCO_F_AUTOSTOP | LOCO_F_RANDOM); locomotives[i].auto_onroute = 0; locomotives[i].auto_way[0] = 0; locomotives[i].auto_wayold[0] = 0; break; } UnLock(); SetSpeed(name, 0); return 1; }; int Locomotives::SetAutoMan(string name) { int i; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) if (name.compare(locomotives[i].name) == 0 && (locomotives[i].flags & LOCO_F_AUTO)) { debug (0, "Locomotives::SetAutoMan (Name:%s)\n", name.c_str()); locomotives[i].flags |= LOCO_F_AUTOSTOP; locomotives[i].flags &= ~LOCO_F_RANDOM; break; } UnLock(); return 1; }; int Locomotives::SetAuto(string name) { int i; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) if (name.compare(locomotives[i].name) == 0) { debug (0, "Locomotives::SetAuto (Name:%s)\n", name.c_str()); locomotives[i].flags |= LOCO_F_AUTO; locomotives[i].flags &= ~LOCO_F_RANDOM; break; } UnLock(); return 1; }; int Locomotives::SetAutoRand(string name) { int i; Lock(); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) if (name.compare(locomotives[i].name) == 0 && (locomotives[i].flags & LOCO_F_AUTO)) { debug (0, "Locomotives::SetRandom (Name:%s)\n", name.c_str()); locomotives[i].flags |= LOCO_F_RANDOM; locomotives[i].flags &= ~LOCO_F_AUTOSTOP; break; } UnLock(); return 1; }; // // set values from bus... // int Locomotives::SetSpeedFromBus(string ifname, int addr, int speed) { int i; JSONParse jp; debug (0, "Locomotives::SetSpeedFromBus IfName:%s Addr:%d Speed:%d", __FILE__, __LINE__, ifname.c_str(), addr, speed); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) { if (ifname.compare(locomotives[i].ifname) == 0 && locomotives[i].addr == addr) { int maxstep; switch(locomotives[i].stepcode) { case LOCO_INT_DCC14: maxstep = 14; break; case LOCO_INT_DCC28: maxstep = 28; break; case LOCO_INT_DCC128: maxstep = 126; break; default: maxstep = -1; break; } if (speed == 0) locomotives[i].speed = 0; if (speed >= (127-((127/maxstep)+1))) locomotives[i].speed = locomotives[i].vmax; else { locomotives[i].speed = speed * locomotives[i].vmax / 127; if (locomotives[i].speed > locomotives[i].vmax) locomotives[i].speed = locomotives[i].vmax; } jp.AddObject("locomotive",_GetJSON(i)); if(network) network->ChangeListPushToAll(jp.ToString()); return 1; } } return 0; }; int Locomotives::SetFunctionFromBus(string ifname, int addr, int func) { int i; JSONParse jp; debug (0, "Locomotives::SetDirectionFromBus IfName:%s Addr:%d function:%d", __FILE__, __LINE__, ifname.c_str(), addr, func); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) { if (ifname.compare(locomotives[i].ifname) == 0 && locomotives[i].addr == addr) { if (func & 32) locomotives[i].flags |= LOCO_F_REVERSE; else locomotives[i].flags &= ~LOCO_F_REVERSE; jp.AddObject("locomotive",_GetJSON(i)); if(network) network->ChangeListPushToAll(jp.ToString()); return 1; } } return 0; }; string Locomotives::GetName(int idx) { string result = ""; Lock(); if (idx <= max && idx >= 0) result = locomotives[idx].name; UnLock(); return result; }; // // with each call only check one single step of the way, if we have to // turn a turnout try to do it and return 0 // if everything is set up till the destination block return 1 // int Locomotives::AutoCheckWaySingleStep(string way, string locname, int *data) { int res = 0; size_t pos1, pos2; size_t curpos; int val, state; int newdata = 0; if (*data < 0) *data = 0; curpos = 0; do { curpos = way.find (",t:", curpos+1); newdata++; if (curpos != string::npos) { pos1 = way.find(":", curpos+3); if (pos1 == string::npos) { debug (0, "%s:%d turnout without value? '%s'", __FILE__, __LINE__, way.c_str()); return 0; } state = server->turnouts.Get(way.substr(curpos+3, pos1-curpos-3)); if (state == -1) { debug (0, "%s:%d turnout not found '%s'", __FILE__, __LINE__, way.substr(curpos+3, pos1-curpos-3).c_str()); return 0; } if (way[pos1+1] == '0' && state != 0) { server->turnouts.Set(way.substr(curpos+3, pos1-curpos-3), 0); break; } else if (way[pos1+1] == '1' && state != 1) { server->turnouts.Set(way.substr(curpos+3, pos1-curpos-3), 1); break; } else if (newdata > *data) { if (way[pos1+1] == '0') server->turnouts.Set(way.substr(curpos+3, pos1-curpos-3), 0); if (way[pos1+1] == '1') server->turnouts.Set(way.substr(curpos+3, pos1-curpos-3), 1); (*data) = newdata; break; } } } while (curpos != string::npos); if (curpos == string::npos) res = 1; return res; } int Locomotives::Loop() { int lnum, i; string way; Locomotive *loco = NULL; string block; string sensor; JSONParse jp; int reverse = 1; for (lnum = 0; lnum < max; lnum++) if (locomotives[lnum].name[0] != 0) { loco = &locomotives[lnum]; if (loco->flags & LOCO_F_REVERSE) reverse = -1; else reverse = 1; if (loco->flags & LOCO_F_AUTO) { // // only in automate do anything alone // if (loco->blockassign[0] == 0) continue; if (loco->auto_onroute == LOCO_OR_NOTHING) { timer_start(&loco->auto_timenext); loco->auto_onroute = LOCO_OR_SEARCH; } else if (loco->auto_onroute == LOCO_OR_SEARCH) { // // 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, 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 { // in here we need to put code for scheduled ways. ? printf ("%s:%d scheduled ways: not even started to work on this.\n", __FILE__, __LINE__); } } // // 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; 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) { // // 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. // block = loco->blocknext+2; 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) { // all turnouts are set, start the train. if ((loco->flags & LOCO_F_CARGO) || (server->blocks.GetFlags(block) & BLOCK_F_SPEEDLIMIT)) SetSpeed(loco->name, reverse * loco->vmid); else SetSpeed(loco->name, reverse * loco->vfast); loco->auto_onroute = LOCO_OR_ONTHEWAY; } else timer_start(&loco->auto_timenext); } } else if (loco->auto_onroute == LOCO_OR_ONTHEWAY) { // // the train is on the way, check for entering the block. // // FIXME: move this code to the block class -> we will need a better code for multiple sensors block = loco->blocknext+2; if (loco->blocknext[0] == '-') sensor = server->blocks.GetSensorMinus(block); else sensor = server->blocks.GetSensorPlus(block); if (server->sensors.GetActive(sensor) == 1) { // entering block? debug (0, "* Locomotive '%s' EnterBlock '%s'", loco->name, loco->blocknext); // 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 (strncmp(loco->blockassign, loco->blockdest, REFERENCENAME_LEN) == 0) { printf ("%s:%d LOCO_OR_ONTHEWAY enter assign == dest stop\n", __FILE__, __LINE__); loco->blockdest[0] = 0; loco->auto_onroute = LOCO_OR_ENTERBLOCKSTOP; SetSpeed(loco->name, reverse * loco->vslow); } else { // try to find new way 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.AddObject("locomotive",_GetJSON(lnum)); 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) { // check enter block block = loco->blockassign+2; if (loco->blockassign[0] == '-') sensor = server->blocks.GetSensorPlus(block); else sensor = server->blocks.GetSensorMinus(block); if (server->sensors.GetActive(sensor) == 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.AddObject("locomotive",_GetJSON(lnum)); if(network) network->ChangeListPushToAll(jp.ToString()); timer_start(&loco->auto_timenext); } } else if (loco->auto_onroute == LOCO_OR_ENTERBLOCKNEXT) { // check enter block int finish = 0; 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) finish = 1; else timer_start(&loco->auto_timenext); } block = loco->blockassign+2; if (loco->blockassign[0] == '-') sensor = server->blocks.GetSensorPlus(block); else sensor = server->blocks.GetSensorMinus(block); if (server->sensors.GetActive(sensor) == 1) { debug (0, "Locomotives::Loop EnterBlockNext '%s' UnLockWay\n", 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 (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) { 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 0; } int Locomotives::Test(string loco) { int res = 0; int i; int j = 0; printf ("%s:%d LocoTest.\n", __FILE__, __LINE__); for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0) if (loco.compare(locomotives[i].name) == 0) { res = AutoCheckWaySingleStep(locomotives[i].auto_way, loco, &j); } printf ("%s:%d LocoTest ---> Return %d\n", __FILE__, __LINE__, res); return 0; };