adding scheduled routes, and fixed some update issues with locomotives

master
Steffen Pohle 4 years ago
parent 0b0339b924
commit 0bdaeaa5e4

@ -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.

@ -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);
}
}

@ -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();

@ -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;

@ -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: <input id=\"locodet_addr\" style=\"width: 50\"> \
Flags: <input id=\"locodet_flags\" style=\"width: 50\"> \
</div> <hr>\
<div> <table><tr><td> \
<table><tr><td> \
<div><table><tr><td> \
<label><input id=\"locodet_auto\" type=\"checkbox\" value=\"\" disabled>Auto</label><br> \
<label><input id=\"locodet_random\" type=\"checkbox\" value=\"\" disabled>Random</label><br> \
</td><td> \
<label><input id=\"locodet_cargo\" type=\"checkbox\" value=\"\">Cargo</label><br> \
<label><input id=\"locodet_short\" type=\"checkbox\" value=\"\">Short Train</label><br> \
<label><input id=\"locodet_canreverse\" type=\"checkbox\" value=\"\">Can Reverse</label><br> \
</td></tr></table> \
</td><td> \
<label><input id=\"locodet_cargo\" type=\"checkbox\" value=\"\">Cargo</label><br> \
</td></tr></table></div> \
\
<div> <table><tr><td> \
<fieldset><legend>Speed</legend> <table>\
<label><input id=\"locodet_reverse\" type=\"checkbox\" value=\"\">Reverse</label><br> \
<tr><td></td><td>Stop</td><td><button id=\"locodet_btnvstop\" type=\"button\" value=\"vstop\">X</button> </td></tr>\
@ -189,7 +200,13 @@ function locodetail_show(loconame) {
</table><button id=\"locodet_RESET\" type=\"button\">Reset</button> \
<button id=\"locodet_TEST\" type=\"button\">Test</button></fileset>\
\
</td></tr></table></div> <hr>\
</td></tr></table></div> \
\
<table><tr><td> \
Sched. Way: <input id=\"locodet_schedway\" style=\"width: 250\" placeholder=\"B:+:B13,W:30,B:-:B42,W:15\"> \
</td></tr></table> \
\
<hr>\
<div align=right> \
<button id=\"locodet_SAVE\" type=\"button\">Save</button> \
<button id=\"locodet_DELETE\" type=\"button\">Delete</button> \
@ -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;
};

@ -1,4 +1,8 @@
<?php
/*
* This code is not used anymore. PHP is just too slow. We went back to the cgi-bin interface
*/
session_start();

@ -455,12 +455,6 @@ function trackDraw() {
if (infoline) infoline.innerHTML = trackMouse.direction;
}
//
// draw possible turnout
else if (mode == "cmd-track-turn") {
var t = trackGetTurnout({x: trackMouse.pos.x, y: trackMouse.pos.y});
}
else if (!mode == "cmd-track-none") alert("track.js: unknown mode:" + mode);
//

Loading…
Cancel
Save