mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-26 17:46:14 +01:00
add HEARTBEAT_CRITICAL to enforce heartbeat check
This commit is contained in:
parent
1d18d5dea5
commit
f7496b7853
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* © 2021 Neil McKechnie
|
||||
* © 2021 Mike S
|
||||
* © 2020-2022 Harald Barth
|
||||
* © 2020-2024 Harald Barth
|
||||
* © 2020-2021 M Steve Todd
|
||||
* © 2020-2021 Chris Harlow
|
||||
* All rights reserved.
|
||||
|
@ -97,12 +97,18 @@ WiThrottle::WiThrottle( int wificlientid) {
|
|||
nextThrottle=firstThrottle;
|
||||
firstThrottle= this;
|
||||
clientid=wificlientid;
|
||||
#ifdef HEARTBEAT_CRITICAL
|
||||
heartBeatEnable=true; // do not run without heartbeat
|
||||
#else
|
||||
heartBeatEnable=false; // until client turns it on
|
||||
#endif
|
||||
mostRecentCab=0;
|
||||
for (int loco=0;loco<MAX_MY_LOCO; loco++) myLocos[loco].throttle='\0';
|
||||
}
|
||||
|
||||
WiThrottle::~WiThrottle() {
|
||||
// emergency stop any loco that was controlled from this throttle
|
||||
eStop();
|
||||
if (Diag::WITHROTTLE) DIAG(F("Deleting WiThrottle client %d"),this->clientid);
|
||||
if (firstThrottle== this) {
|
||||
firstThrottle=this->nextThrottle;
|
||||
|
@ -140,7 +146,12 @@ void WiThrottle::parse(RingStream * stream, byte * cmdx) {
|
|||
switch (cmd[0]) {
|
||||
case '*': // heartbeat control
|
||||
if (cmd[1]=='+') heartBeatEnable=true;
|
||||
else if (cmd[1]=='-') heartBeatEnable=false;
|
||||
else if (cmd[1]=='-') {
|
||||
#ifdef HEARTBEAT_CRITICAL
|
||||
eStop();
|
||||
#endif
|
||||
heartBeatEnable=false;
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
if (cmd[1]=='P' && cmd[2]=='A' ) { //PPA power mode
|
||||
|
@ -303,10 +314,14 @@ void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar,
|
|||
switch (aval[0]) {
|
||||
case 'V': // Vspeed
|
||||
{
|
||||
int witSpeed=getInt(aval+1);
|
||||
uint8_t dccSpeed = WiTToDCCSpeed(getInt(aval+1));
|
||||
#ifdef HEARTBEAT_CRITICAL
|
||||
if (heartBeatEnable == false) // if there is no heartBeat, keep throttle at
|
||||
dccSpeed = 1; // emegency stop (dccSpeed 1)
|
||||
#endif
|
||||
LOOPLOCOS(throttleChar, cab) {
|
||||
mostRecentCab=myLocos[loco].cab;
|
||||
DCC::setThrottle(myLocos[loco].cab, WiTToDCCSpeed(witSpeed), DCC::getThrottleDirection(myLocos[loco].cab));
|
||||
DCC::setThrottle(myLocos[loco].cab, dccSpeed, DCC::getThrottleDirection(myLocos[loco].cab));
|
||||
// SetThrottle will cause speed change broadcast
|
||||
}
|
||||
}
|
||||
|
@ -394,21 +409,30 @@ void WiThrottle::loop(RingStream * stream) {
|
|||
wt->checkHeartbeat(stream);
|
||||
}
|
||||
|
||||
void WiThrottle::checkHeartbeat(RingStream * stream) {
|
||||
// if eStop time passed... eStop any locos still assigned to this client and then drop the connection
|
||||
if(heartBeatEnable && (millis()-heartBeat > ESTOP_SECONDS*1000)) {
|
||||
if (Diag::WITHROTTLE) DIAG(F("%l WiThrottle(%d) eStop(%ds) timeout, drop connection"), millis(), clientid, ESTOP_SECONDS);
|
||||
void WiThrottle::eStop() {
|
||||
LOOPLOCOS('*', -1) {
|
||||
if (myLocos[loco].throttle!='\0') {
|
||||
if (Diag::WITHROTTLE) DIAG(F("%l eStopping cab %d"),millis(),myLocos[loco].cab);
|
||||
DCC::setThrottle(myLocos[loco].cab, 1, DCC::getThrottleDirection(myLocos[loco].cab)); // speed 1 is eStop
|
||||
heartBeat=millis(); // We have just stopped everyting, we don't need to do that again at next loop.
|
||||
}
|
||||
}
|
||||
// if it does come back, the throttle should re-acquire
|
||||
}
|
||||
|
||||
void WiThrottle::checkHeartbeat(RingStream * stream) {
|
||||
// if eStop time passed... eStop any locos still assigned to this client and then drop the connection
|
||||
if(heartBeatEnable && (millis()-heartBeat > ESTOP_SECONDS*1000)) {
|
||||
if (Diag::WITHROTTLE) DIAG(F("%l WiThrottle(%d) eStop(%ds) timeout"), millis(), clientid, ESTOP_SECONDS);
|
||||
if (missedHeartbeatCounter++ > 10) {
|
||||
if (Diag::WITHROTTLE) DIAG(F("Too many missed heartbeats, drop connection"));
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
eStop();
|
||||
heartBeat=millis(); // We have just stopped everyting, we don't need to do that again at next loop.
|
||||
// Destructor will take care of estop. If it does come back, the throttle should re-acquire
|
||||
// delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
// send any outstanding speed/direction/function changes for this clients locos
|
||||
// Changes may have been caused by this client, or another non-Withrottle or Exrail
|
||||
|
|
13
WiThrottle.h
13
WiThrottle.h
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* © 2021 Mike S
|
||||
* © 2020-2021 Chris Harlow
|
||||
* © 2024 Harald Barth
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of Asbelos DCC API
|
||||
|
@ -20,7 +21,7 @@
|
|||
*/
|
||||
#ifndef WiThrottle_h
|
||||
#define WiThrottle_h
|
||||
|
||||
#include "defines.h"
|
||||
#include "RingStream.h"
|
||||
|
||||
struct MYLOCO {
|
||||
|
@ -45,9 +46,15 @@ class WiThrottle {
|
|||
~WiThrottle();
|
||||
|
||||
static const int MAX_MY_LOCO=10; // maximum number of locos assigned to a single client
|
||||
#ifdef HEARTBEAT_CRITICAL
|
||||
static const int HEARTBEAT_SECONDS=1;
|
||||
static const int HEARTBEAT_PRELOAD=2;
|
||||
static const int ESTOP_SECONDS=3;
|
||||
#else
|
||||
static const int HEARTBEAT_SECONDS=10; // heartbeat at 10 secs to provide messaging transport
|
||||
static const int HEARTBEAT_PRELOAD=2; // request fast callback when connecting multiple messages
|
||||
static const int ESTOP_SECONDS=20; // eStop if no incoming messages for more than 8secs
|
||||
static const int ESTOP_SECONDS=20; // eStop if no incoming messages for more than 20secs
|
||||
#endif
|
||||
static WiThrottle* firstThrottle;
|
||||
static int getInt(byte * cmd);
|
||||
static int getLocoId(byte * cmd);
|
||||
|
@ -62,6 +69,7 @@ class WiThrottle {
|
|||
MYLOCO myLocos[MAX_MY_LOCO];
|
||||
bool heartBeatEnable;
|
||||
unsigned long heartBeat;
|
||||
uint8_t missedHeartbeatCounter = 0;
|
||||
bool introSent=false;
|
||||
bool turnoutsSent=false;
|
||||
bool rosterSent=false;
|
||||
|
@ -75,6 +83,7 @@ class WiThrottle {
|
|||
void multithrottle(RingStream * stream, byte * cmd);
|
||||
void locoAction(RingStream * stream, byte* aval, char throttleChar, int cab);
|
||||
void accessory(RingStream *, byte* cmd);
|
||||
void eStop();
|
||||
void checkHeartbeat(RingStream * stream);
|
||||
void markForBroadcast2(int cab);
|
||||
void sendIntro(Print * stream);
|
||||
|
|
Loading…
Reference in New Issue
Block a user