Skip to content

Commit

Permalink
Fix for individual loco direction (facing) changes in a consist
Browse files Browse the repository at this point in the history
  • Loading branch information
flash62au committed Sep 2, 2024
1 parent 4744639 commit 63f9a70
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 45 deletions.
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=WiThrottleProtocol
version=1.1.22
version=1.1.23
author=Peter Akers <akersp62@gmail.com>, David Zuhn <zoo@statebeltrailway.org>, Luca Dentella <luca@dentella.it>
maintainer=Peter Akers <akersp62@gmail.com>
sentence=JMRI WiThrottle Protocol implementation for ESP32
Expand Down
156 changes: 112 additions & 44 deletions src/WiThrottleProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,39 +319,65 @@ bool WiThrottleProtocol::processLocomotiveAction(char multiThrottle, char *c, in
if (logLevel>1) console->printf("WiT:: currentAddress is '%s'\n", currentAddress[multiThrottleIndex].c_str());
}

bool isLeadOrAll = true;
String address = "";
String addrCheck = currentAddress[multiThrottleIndex] + PROPERTY_SEPARATOR;
String allCheck = "*";
allCheck.concat(PROPERTY_SEPARATOR);
if (remainder.startsWith(addrCheck)) {
remainder.remove(0, addrCheck.length());
}
else if (remainder.startsWith(allCheck)) {
} else if (remainder.startsWith(allCheck)) {
remainder.remove(0, allCheck.length());
} else {
int p = remainder.indexOf(PROPERTY_SEPARATOR);
if (p > 0) { // non-lead loco
address = remainder.substring(0, p);
addrCheck = address + PROPERTY_SEPARATOR;
remainder.remove(0, addrCheck.length());
isLeadOrAll = false;
}
}

if (logLevel>1) console->printf("WiT:: processLocomotiveAction: after separator is %s\n", remainder.c_str());

if (remainder.length() > 0) {
char action = remainder[0];

switch (action) {
case 'F':
if (logLevel>1) console->printf("WiT:: processing function state\n");
processFunctionState(multiThrottle, remainder);
break;
case 'V':
processSpeed(multiThrottle, remainder);
break;
case 's':
processSpeedSteps(multiThrottle, remainder);
break;
case 'R':
processDirection(multiThrottle, remainder);
break;
default:
if (logLevel>0) console->printf("WiT:: unrecognized action '%c'\n", action);
// no processing on unrecognized actions
break;
if (isLeadOrAll) {
switch (action) {
case 'F':
if (logLevel>1) console->printf("WiT:: processing function state\n");
processFunctionState(multiThrottle, remainder);
break;
case 'V':
processSpeed(multiThrottle, remainder);
break;
case 's':
processSpeedSteps(multiThrottle, remainder);
break;
case 'R':
processDirection(multiThrottle, remainder);
break;
default:
if (logLevel>0) console->printf("WiT:: unrecognized action '%c'\n", action);
// no processing on unrecognized actions
break;
}
} else { // non-lead loco
if (logLevel>0) console->printf("WiT:: Non-lead loco action '%c'\n", action);
switch (action) {
case 'F':
case 'V':
case 's':
break;
case 'R':
processDirection(multiThrottle, address, remainder);
break;
default:
if (logLevel>0) console->printf("WiT:: unrecognized action '%c'\n", action);
// no processing on unrecognized actions
break;
}
}
return true;
}
Expand Down Expand Up @@ -920,14 +946,13 @@ void WiThrottleProtocol::processSpeedSteps(char multiThrottle, const String& spe


void WiThrottleProtocol::processDirection(char multiThrottle, const String& directionStr) {
if (logLevel>0) { console->print("WiT:: processDirection(): "); console->println(multiThrottle); }
if (logLevel>0) { }

int multiThrottleIndex = getMultiThrottleIndex(multiThrottle);
if (logLevel>0) {
console->print("WiT:: DIRECTION STRING: ");
console->println(directionStr);
console->print("LENGTH: ");
console->println(directionStr.length());
console->print("WiT:: processDirection(): throttle: "); console->println(multiThrottle);
console->print(" DIRECTION STRING: "); console->println(directionStr);
console->print(" LENGTH: "); console->println(directionStr.length());
}

// R[0|1]
Expand All @@ -949,6 +974,38 @@ void WiThrottleProtocol::processDirection(char multiThrottle, const String& dire
if (logLevel>1) console->println("WiT:: processDirection(): end");
}

// should only ever be called for the non-lead locos
void WiThrottleProtocol::processDirection(char multiThrottle, String& address, const String& directionStr) {
int multiThrottleIndex = getMultiThrottleIndex(multiThrottle);
Direction direction = Forward;
if (directionStr.charAt(1) == '0') direction = Reverse;

if (logLevel>0) {
console->print("WiT:: processDirection(): (facing) throttle: "); console->println(multiThrottle);
console->print(" Address: "); console->println(address); ;
console->print(" DIRECTION STRING: "); console->println(directionStr);
console->print(" LENGTH: "); console->println(directionStr.length());
}

// R[0|1]
if (delegate && directionStr.length() == 2) {
for(int i=0;i<locomotives[multiThrottleIndex].size();i++) {
if (locomotives[multiThrottleIndex][i].equals(address)) {
locomotivesFacing[multiThrottleIndex][i] = direction;

if (multiThrottle == DEFAULT_MULTITHROTTLE) {
delegate->receivedDirection(address, direction);
} else {
delegate->receivedDirectionMultiThrottle(multiThrottle, address, direction);
}
break;
}
}
}

if (logLevel>1) console->println("WiT:: processDirection(): end");
}



void WiThrottleProtocol::processTrackPower(char *c, int len) {
Expand Down Expand Up @@ -1097,7 +1154,15 @@ bool WiThrottleProtocol::checkHeartbeat() {
char multiThrottleChar = '0' + i;
if (getNumberOfLocomotives(multiThrottleChar)>0) {
setSpeed(multiThrottleChar, getSpeed(multiThrottleChar), true);
setDirection(multiThrottleChar, getDirection(multiThrottleChar), true);
int multiThrottleIndex = getMultiThrottleIndex(multiThrottleChar);
if (locomotives[multiThrottleIndex].size()==1) {
setDirection(multiThrottleChar, getDirection(multiThrottleChar), true);
} else {
for(int i=0;i<locomotives[multiThrottleIndex].size();i++) {
String loco = getLocomotiveAtPosition(multiThrottleChar,i);
setDirection(multiThrottleChar, loco, getDirection(multiThrottleChar, loco), true);
}
}
}
}
}
Expand Down Expand Up @@ -1372,34 +1437,35 @@ bool WiThrottleProtocol::setDirection(char multiThrottle, String address, Direct
}

bool WiThrottleProtocol::setDirection(char multiThrottle, String address, Direction direction, bool forceSend) {
if (logLevel>0) { console->print("WiT:: setDirection(): "); console->print(multiThrottle); console->print(" : "); console->println(direction); }
if (logLevel>0) { console->print("WiT:: setDirection(): address: "); console->print(address); console->print(" throttle: ");
console->print(multiThrottle); console->print(" direction: "); console->println(direction); }

int multiThrottleIndex = getMultiThrottleIndex(multiThrottle);
if (!locomotiveSelected[multiThrottleIndex]) {
return false;
}

if ( (direction != currentDirection[multiThrottleIndex]) || (forceSend) ) {
String cmd = "M" + String(multiThrottle) + "A" + address;
cmd.concat(PROPERTY_SEPARATOR);
cmd.concat("R");
if (direction == Reverse) {
cmd += "0";
}
else {
cmd += "1";
String directionString = (direction == Reverse) ? "0" : "1";
Direction currentDir = currentDirection[multiThrottleIndex];
int locoIndex = -1;
if (!address.equals(ALL_LOCOS_ON_THROTTLE)) {
for(int i=0;i<locomotives[multiThrottleIndex].size();i++) {
if (locomotives[multiThrottleIndex][i].equals(address)) {
locoIndex = i;
currentDir = locomotivesFacing[multiThrottleIndex][i];
break;
}
}
}

if ( (direction != currentDir) || (forceSend) ) {
String cmd = "M" + String(multiThrottle) + "A" + address + PROPERTY_SEPARATOR + "R" + directionString;
sendDelayedCommand(cmd);

if (address.equals(ALL_LOCOS_ON_THROTTLE)) {
if (locoIndex == -1) { // all locos
currentDirection[multiThrottleIndex] = direction;
} else {
for(int i=0;i<locomotives[multiThrottleIndex].size();i++) {
if (locomotives[multiThrottleIndex][i].equals(address)) {
locomotivesFacing[multiThrottleIndex][i] = direction;
break;
}
}
locomotivesFacing[multiThrottleIndex][locoIndex] = direction;
}
}
return true;
Expand All @@ -1416,11 +1482,12 @@ Direction WiThrottleProtocol::getDirection(char multiThrottle) {
}

Direction WiThrottleProtocol::getDirection(char multiThrottle, String address) {
if (logLevel>0) { console->print("WiT:: getDirection(): "); console->println(multiThrottle); }
if (logLevel>0) { console->print("WiT:: getDirection(): addr: "); console->print(address); console->print(" throttle: "); console->println(multiThrottle); }

int multiThrottleIndex = getMultiThrottleIndex(multiThrottle);

if (address.equals(ALL_LOCOS_ON_THROTTLE)) {
if (logLevel>0) { console->print("WiT:: getDirection(): all dir: "); console->println(currentDirection[multiThrottleIndex]); }
return currentDirection[multiThrottleIndex];
} else {
Direction individualDirection = currentDirection[multiThrottleIndex];
Expand All @@ -1430,6 +1497,7 @@ Direction WiThrottleProtocol::getDirection(char multiThrottle, String address) {
break;
}
}
if (logLevel>0) { console->print("WiT:: getDirection(): individual dir: "); console->println(individualDirection); }
return individualDirection;
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/WiThrottleProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/*
Version information:
1.1.23 - Fix for individual loco direction (facing) changes in a consist
1.1.22 - Fix for the original 'steal' code
1.1.21 - Add support for setting the Speed Step mode 28/128/14 etc. setSpeedSteps(), getSpeedSteps()
1.1.20 - Corrected the EStop for 'all' throttles
Expand Down Expand Up @@ -243,6 +244,11 @@ class WiThrottleProtocolDelegate
/// @param dir TBA
virtual void receivedDirection(Direction dir) { } // R{0,1}

/// @brief Delegate method to receive the direction for the default (first) throttle for an individual loco from the Withrottle Server
/// @param dir TBA
/// @param loco TBA
virtual void receivedDirection(String address, Direction dir) { } // R{0,1}

/// @brief Delegate method to receive the number of speed steps for the default (first) throttle from the Withrottle Server
/// @param steps 1=128step, 2=28step, 4=27step or 8=14step
virtual void receivedSpeedSteps(int steps) { } // snn
Expand All @@ -257,6 +263,12 @@ class WiThrottleProtocolDelegate
/// @param dir TBA
virtual void receivedDirectionMultiThrottle(char multiThrottle, Direction dir) { } // R{0,1}

/// @brief Delegate method to receive the direction for a specific throttle for an individual loco from the Withrottle Server
/// @param multiThrottle Which Throttle. Supported multiThrottle codes are 'T' '0' '1' '2' '3' '4' '5' only.
/// @param dir TBA
/// @param loco TBA
virtual void receivedDirectionMultiThrottle(char multiThrottle, String address, Direction dir) { } // R{0,1}

/// @brief Delegate method to receive the speed steps for a specific throttle from the Withrottle Server
/// @param multiThrottle Which Throttle. Supported multiThrottle codes are 'T' '0' '1' '2' '3' '4' '5' only.
/// @param steps 1=128step, 2=28step, 4=27step or 8=14step
Expand Down Expand Up @@ -716,6 +728,12 @@ class WiThrottleProtocol
/// @param directionStr TBA
void processDirection(char multiThrottle, const String& directionStr);

/// @brief Process an incoming Direction command from the Command Station for a specific multiThrottle
/// @param multithrottle Which Throttle. Supported multiThrottle codes are 'T' '0' '1' '2' '3' '4' '5' only.
/// @param loco TBA
/// @param directionStr TBA
void processDirection(char multiThrottle, String& loco, const String& directionStr);

/// @brief Process an incoming Speed command from the Command Station for a specific multiThrottle
/// @param speedData TBA
void processSpeed(char multiThrottle, const String& speedData);
Expand Down

0 comments on commit 63f9a70

Please sign in to comment.