From 0bdaeaa5e491a5566e328fb48d3492e154587e56 Mon Sep 17 00:00:00 2001 From: Steffen Pohle Date: Sat, 11 Dec 2021 00:40:29 +0100 Subject: [PATCH] adding scheduled routes, and fixed some update issues with locomotives --- ChangeLog | 4 ++ server/locomotive.cc | 123 +++++++++++++++++++++++++++++++++-- server/locomotive.h | 12 ++-- webinterface/gui/gui.css | 2 +- webinterface/locomotive.js | 38 ++++++++--- webinterface/serverinout.php | 4 ++ webinterface/track.js | 6 -- 7 files changed, 163 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 100b367..280b6a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2021-12-10: +- adding support for scheduling ways +- fixed: webinterface, update on loco will now change its detail display + 2021-12-02: - mark blocks as onlyCARGO or onlyPESSANGER, random-automode looks nice now. - webinterface: debug messages will be print to the console. diff --git a/server/locomotive.cc b/server/locomotive.cc index 9c7a0f6..b9fcb57 100644 --- a/server/locomotive.cc +++ b/server/locomotive.cc @@ -45,6 +45,7 @@ JSONParse Locomotives::_GetJSON(int idx) { 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); + s = locomotives[idx].schedway; json.AddObject("schedway", s); json.AddObject("addr", locomotives[idx].addr); json.AddObject("stepcode", locomotives[idx].stepcode); json.AddObject("speed", locomotives[idx].speed); @@ -118,6 +119,7 @@ Locomotive Locomotives::GetLocomotiveFromJSON(JSONParse *j) { l.flags = 0; l.speed = 0; l.func = 0; + l.schedway[0] = 0; l.blockassign[0] = 0; l.blockdest[0] = 0; l.blocknext[0] = 0; @@ -140,6 +142,9 @@ Locomotive Locomotives::GetLocomotiveFromJSON(JSONParse *j) { strncpy (l.blockprev, s.c_str(), REFERENCENAME_LEN); j->GetValue("blocknext", &s); strncpy (l.blocknext, s.c_str(), REFERENCENAME_LEN); + j->GetValue("schedway", &s); + strncpy (l.schedway, s.c_str(), WAYDATA_LEN); + j->GetValueInt("addr", &l.addr); j->GetValueInt("stepcode", &l.stepcode); j->GetValueInt("speed", &l.speed); @@ -155,6 +160,11 @@ Locomotive Locomotives::GetLocomotiveFromJSON(JSONParse *j) { }; +/* + * this function gets called if some configuration data has changed. + * We will ignore the functions and speed settings. This has to be set with the SetFunction + * and SetSpeed calls. + */ int Locomotives::Change(Locomotive *loco) { int i; int ifree = -1; @@ -174,8 +184,7 @@ int Locomotives::Change(Locomotive *loco) { locomotives[i].vfast = loco->vfast; locomotives[i].vmax = loco->vmax; locomotives[i].flags = loco->flags; -// locomotives[i].speed = 0; -// locomotives[i].func = 0; + strncpy (locomotives[i].schedway, loco->schedway, WAYDATA_LEN); ifree = i; break; @@ -189,6 +198,7 @@ int Locomotives::Change(Locomotive *loco) { locomotives[ifree] = *loco; strncpy (locomotives[ifree].name, loco->name, REFERENCENAME_LEN); strncpy (locomotives[ifree].ifname, loco->ifname, REFERENCENAME_LEN); + strncpy (locomotives[ifree].schedway, loco->schedway, WAYDATA_LEN); } changed = 1; @@ -206,6 +216,7 @@ int Locomotives::Delete(string name) { if (name.compare(locomotives[i].name) == 0) { locomotives[i].name[0] = 0; locomotives[i].ifname[0] = 0; + locomotives[i].schedway[0] = 0; locomotives[i].addr = 0; locomotives[i].stepcode = 0; locomotives[i].vmin = 0; @@ -384,7 +395,10 @@ int Locomotives::Reset(string name) { locomotives[i].blocknext[0] = 0; locomotives[i].auto_way[0] = 0; locomotives[i].auto_wayold[0] = 0; - locomotives[i].auto_onroute = -1; + locomotives[i].auto_onroute = 0; + locomotives[i].auto_data = 0; + locomotives[i].auto_timenext = { 0 }; + locomotives[i].sched_step = 0; break; } @@ -408,6 +422,7 @@ int Locomotives::SetMan(string name) { locomotives[i].auto_onroute = 0; locomotives[i].auto_way[0] = 0; locomotives[i].auto_wayold[0] = 0; + locomotives[i].sched_step = 0; break; } UnLock(); @@ -534,6 +549,87 @@ string Locomotives::GetName(int idx) { }; +/* + * Locomotive is on auto, do the scheduled steps + */ +int Locomotives::SchedulerNextStep(Locomotive *loc) { + int stepsmax = 0; // number of found steps + int stepcurpos = 0; // current pos in way string + int stepnextpos = -1; // next pos; + int schedwaylen = 0; + int i; + string name; + string next; + + if (loc == NULL) return 0; + + debug (0, "Locomotives::SchedulerNextStep loc:%s Step:%d", loc->name, loc->sched_step); + name = loc->name; + + // + // find number of scheduled steps, current pos and next pos + for (i = 0; i < WAYDATA_LEN && loc->schedway[i] != 0; i++) + if (loc->schedway[i] == ',') { + stepsmax++; + if (stepsmax == loc->sched_step) stepcurpos = i; + else if (loc->sched_step == 0 || (stepcurpos > 0 && stepnextpos == -1)) stepnextpos = i+1; + } + schedwaylen = i; + if (stepnextpos == -1) stepnextpos = 0; // no next step found point to first + + // + // set next way + if (stepnextpos == 0) loc->sched_step = 0; + else loc->sched_step++; + if (loc->sched_step > stepsmax) { + loc->sched_step = 0; + stepnextpos = 0; + } + + // read parameter of step + for (next = "", i = stepnextpos; i < WAYDATA_LEN && loc->schedway[i] != ',' && loc->schedway[i] != 0; i++) { + if (i > stepnextpos+1) next += loc->schedway[i]; + } + debug (0, "Locomotives::SchedulerNextStep loc:%s Next Pos: '%s'", loc->name, loc->schedway+stepnextpos); + + if (loc->schedway[stepnextpos] && stepnextpos < schedwaylen-2) { + + switch (loc->schedway[stepnextpos]) { + case ('W'): + case ('w'): + gettimeofday (&loc->auto_timenext, NULL); + loc->auto_timenext.tv_sec += atoi (next.c_str()); + loc->auto_data = 0; + loc->auto_onroute = LOCO_OR_STOPWAIT; + break; + case ('B'): + case ('b'): + gettimeofday (&loc->auto_timenext, NULL); + snprintf (loc->blockdest, REFERENCENAME_LEN, "%s", next.c_str()); + loc->auto_timenext.tv_sec += atoi (next.c_str()); + loc->auto_data = 0; + loc->auto_onroute = LOCO_OR_SEARCH; + break; + case ('R'): + case ('r'): + if (loc->blockassign[0] == '-') loc->blockassign[0] = '+'; + else if (loc->blockassign[0] == '+') loc->blockassign[0] = '-'; + + if (loc->flags & LOCO_F_REVERSE) loc->flags &= ~LOCO_F_REVERSE; + else loc->flags |= LOCO_F_REVERSE; + + break; + default: + debug (0, "Locomotives::SchedulerNextStep Unknown Command: '%c' loc:%s way:'%s'", loc->name, + loc->schedway[stepnextpos], loc->schedway); + break; + } + } + + SendUpdate(loc); + + return 0; +} // // with each call only check one single step of the way, if we have to @@ -589,6 +685,24 @@ int Locomotives::AutoCheckWaySingleStep(string way, string locname, int *data) { } +void::Locomotives::SendUpdate (Locomotive *loc) { + int lnum; + JSONParse jp; + + if (locomotives == NULL) return; + + for (lnum = 0; lnum < max; lnum++) { + if (loc == &locomotives[lnum]) { + jp.Clear(); + jp.AddObject("locomotive",_GetJSON(lnum)); + if(network) network->ChangeListPushToAll(jp.ToString()); + break; + } + } + +} + + int Locomotives::Loop() { int lnum, i; string way; @@ -669,8 +783,7 @@ int Locomotives::Loop() { } } 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__); + SchedulerNextStep(loco); } } diff --git a/server/locomotive.h b/server/locomotive.h index 6002f1a..46d81ff 100644 --- a/server/locomotive.h +++ b/server/locomotive.h @@ -29,7 +29,7 @@ enum { LOCO_OR_NOTHING = 0, LOCO_OR_SEARCH, // search way (to next block and lock way) LOCO_OR_PREPARE, // switch turnouts right way (one every 100ms) - // if no turnout has to be set, continue + // if no turnout has to been set, continue LOCO_OR_ONTHEWAY, // locomotive is on the way // maybe prepare next block? // ASSIGN -> PREV, NEXT -> ASSIGN, NEXT <- (empty) // propabely searching next block (if DEST is set)? @@ -39,11 +39,6 @@ enum { LOCO_OR_STOPWAIT // stopping }; -struct s_LocoAuto { - int onroute; // LOCO_OR_..... - struct timeval waituntil; // wait until this time for next action (tournout, waiting station...) -}; - struct s_Locomotive { char name[REFERENCENAME_LEN]; // name char ifname[REFERENCENAME_LEN]; // ref. of interface @@ -55,6 +50,7 @@ struct s_Locomotive { int vmid; // speed - for normal trains (max for cargo trains, on automode) int vfast; // speed - for normal trains int vmax; // speed - maximum speed + char schedway[WAYDATA_LEN]; // scheduled way W:15,B:+B17,W30,B:-B21 // dynamic data int speed; // current speed @@ -64,6 +60,7 @@ struct s_Locomotive { char blockprev[REFERENCENAME_LEN]; // prev block (mostly assigned block char blockdest[REFERENCENAME_LEN]; // destination block + int sched_step; // on automode this is the scheduled way step char auto_way[WAYDATA_LEN]; // route to way "b:+blockname,t:name:0,t:name:1,b:-blockname" char auto_wayold[WAYDATA_LEN]; // route to way "b:+blockname,t:name:0,t:name:1,b:-blockname" int auto_onroute; // LOCO_OR_.... @@ -71,6 +68,7 @@ struct s_Locomotive { struct timeval auto_timenext; // timeval of the next active step } typedef Locomotive; + class Locomotives { private: Locomotive *locomotives; @@ -83,6 +81,8 @@ class Locomotives { // not thread safe JSONParse _GetJSON(int idx); + int SchedulerNextStep(Locomotive *loc); // automode, calculate next step + void SendUpdate(Locomotive *loc); public: Locomotives(); diff --git a/webinterface/gui/gui.css b/webinterface/gui/gui.css index dd53169..d3d5d92 100644 --- a/webinterface/gui/gui.css +++ b/webinterface/gui/gui.css @@ -91,7 +91,7 @@ button { input { - border: 1px solid var(--input-bg-color); + border: 1px solid var(--input-fg-color); background-color: var(--input-bg-color); color: var(--input-fg-color); font-family: "Lucida Console", Courier, monospace; diff --git a/webinterface/locomotive.js b/webinterface/locomotive.js index ff72366..e4fd1d6 100644 --- a/webinterface/locomotive.js +++ b/webinterface/locomotive.js @@ -19,6 +19,8 @@ var locomotives = []; function locomotive_Update(data) { for (var i = 0; i < locomotives.length; i++) { if (data.name == locomotives[i].name) { + var loco_name = document.getElementById("locodet_name"); + debug ("Update Locomotive:" + locomotives[i].name + " with Locomotive:" + data.name); locomotives[i].name = data.name; locomotives[i].ifname = data.ifname; @@ -32,11 +34,18 @@ function locomotive_Update(data) { locomotives[i].vmax = data.vmax; locomotives[i].flags = data.flags; if (data.blockassign) locomotives[i].blockassign = data.blockassign; + else locomotives[i].blockassign = ""; if (data.blockprev) locomotives[i].blockprev = data.blockprev; + else locomotives[i].blockprev = ""; if (data.blocknext) locomotives[i].blocknext = data.blocknext; + else locomotives[i].blocknext = ""; if (data.blockdest) locomotives[i].blockdest = data.blockdest; + else locomotives[i].blockdest = ""; + if (data.schedway) locomotives[i].schedway = data.schedway; + else locomotives[i].schedway = ""; if (data.auto_way) locomotives[i].auto_way = data.auto_way; - locodetail_setData(locomotives[i]); + if (loco_name.value == data.name) locodetail_setData(locomotives[i]); + lococtrl_setData(data); return; } @@ -60,6 +69,7 @@ function locomotive_Update(data) { blockdest: data.blockdest, blocknext: data.blocknext, blockprev: data.blockprev, + schedway: data.schedway, auto_way: data.auto_way }); @@ -152,16 +162,17 @@ function locodetail_show(loconame) { Adress: \ Flags: \
\ -
\ -
\ +
\
\
\
\ -
\
\
\ -
\ +
\ +
\ +
\ \ +
\
Speed \
\ \ @@ -189,7 +200,13 @@ function locodetail_show(loconame) {
Stop
\ \ \ -

\ +
\ + \ +
\ + Sched. Way: \ +
\ + \ +
\
\ \ \ @@ -226,7 +243,7 @@ function locodetail_show(loconame) { // // load default values var res = { name: "", ifname: "", addr: "", flags: 0, steps: "", - vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100" }; + vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100", schedway: "" }; locodetail_setData(res); if (loconame) { @@ -450,6 +467,7 @@ function locodetail_setData(elm) { var loco_blocknext = document.getElementById("locodet_blocknext"); var loco_blockprev = document.getElementById("locodet_blockprev"); var loco_auto_way = document.getElementById("locodet_auto_way"); + var loco_schedway = document.getElementById("locodet_schedway"); if (elm) { if (loco_name) loco_name.value = elm.name; @@ -490,6 +508,8 @@ function locodetail_setData(elm) { if (loco_blockdest) loco_blockdest.value = elm.blockdest; if (loco_blocknext) loco_blocknext.value = elm.blocknext; if (loco_blockprev) loco_blockprev.value = elm.blockprev; + if (loco_schedway && elm.schedway) loco_schedway.value = elm.schedway; + else loco_schedway.value = ""; if (loco_auto_way) loco_auto_way.value = elm.auto_way; } @@ -509,7 +529,7 @@ function locodetail_setData(elm) { // function locodetail_getData() { var res = { name: "", ifname: "", addr: "", flags: 0, stepcode:"0", - vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100" }; + vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100", schedway: "" }; var codes = document.getElementsByName('STEPCODE'); for(var i = 0; i < codes.length; i++){ @@ -528,6 +548,7 @@ function locodetail_getData() { var loco_vfast = document.getElementById("locodet_vfast"); var loco_vmax = document.getElementById("locodet_vmax"); var loco_speed = document.getElementById("locodet_speed"); + var loco_schedway = document.getElementById("locodet_schedway"); if (loco_name) res.name = loco_name.value; if (loco_ifname) res.ifname = loco_ifname.value; @@ -539,6 +560,7 @@ function locodetail_getData() { if (loco_vfast) res.vfast = loco_vfast.value; if (loco_vmax) res.vmax = loco_vmax.value; if (loco_speed) res.speed = loco_speed.speed; + if (loco_schedway) res.schedway = loco_schedway.value; return res; }; diff --git a/webinterface/serverinout.php b/webinterface/serverinout.php index ace2bab..ed6238a 100644 --- a/webinterface/serverinout.php +++ b/webinterface/serverinout.php @@ -1,4 +1,8 @@