mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-03-14 18:13:09 +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 Neil McKechnie
|
||||||
* © 2021 Mike S
|
* © 2021 Mike S
|
||||||
* © 2020-2022 Harald Barth
|
* © 2020-2024 Harald Barth
|
||||||
* © 2020-2021 M Steve Todd
|
* © 2020-2021 M Steve Todd
|
||||||
* © 2020-2021 Chris Harlow
|
* © 2020-2021 Chris Harlow
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@ -97,12 +97,18 @@ WiThrottle::WiThrottle( int wificlientid) {
|
|||||||
nextThrottle=firstThrottle;
|
nextThrottle=firstThrottle;
|
||||||
firstThrottle= this;
|
firstThrottle= this;
|
||||||
clientid=wificlientid;
|
clientid=wificlientid;
|
||||||
|
#ifdef HEARTBEAT_CRITICAL
|
||||||
|
heartBeatEnable=true; // do not run without heartbeat
|
||||||
|
#else
|
||||||
heartBeatEnable=false; // until client turns it on
|
heartBeatEnable=false; // until client turns it on
|
||||||
|
#endif
|
||||||
mostRecentCab=0;
|
mostRecentCab=0;
|
||||||
for (int loco=0;loco<MAX_MY_LOCO; loco++) myLocos[loco].throttle='\0';
|
for (int loco=0;loco<MAX_MY_LOCO; loco++) myLocos[loco].throttle='\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
WiThrottle::~WiThrottle() {
|
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 (Diag::WITHROTTLE) DIAG(F("Deleting WiThrottle client %d"),this->clientid);
|
||||||
if (firstThrottle== this) {
|
if (firstThrottle== this) {
|
||||||
firstThrottle=this->nextThrottle;
|
firstThrottle=this->nextThrottle;
|
||||||
@ -140,7 +146,12 @@ void WiThrottle::parse(RingStream * stream, byte * cmdx) {
|
|||||||
switch (cmd[0]) {
|
switch (cmd[0]) {
|
||||||
case '*': // heartbeat control
|
case '*': // heartbeat control
|
||||||
if (cmd[1]=='+') heartBeatEnable=true;
|
if (cmd[1]=='+') heartBeatEnable=true;
|
||||||
else if (cmd[1]=='-') heartBeatEnable=false;
|
else if (cmd[1]=='-') {
|
||||||
|
#ifdef HEARTBEAT_CRITICAL
|
||||||
|
eStop();
|
||||||
|
#endif
|
||||||
|
heartBeatEnable=false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
if (cmd[1]=='P' && cmd[2]=='A' ) { //PPA power mode
|
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]) {
|
switch (aval[0]) {
|
||||||
case 'V': // Vspeed
|
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) {
|
LOOPLOCOS(throttleChar, cab) {
|
||||||
mostRecentCab=myLocos[loco].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
|
// SetThrottle will cause speed change broadcast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -394,19 +409,28 @@ void WiThrottle::loop(RingStream * stream) {
|
|||||||
wt->checkHeartbeat(stream);
|
wt->checkHeartbeat(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void WiThrottle::checkHeartbeat(RingStream * stream) {
|
void WiThrottle::checkHeartbeat(RingStream * stream) {
|
||||||
// if eStop time passed... eStop any locos still assigned to this client and then drop the connection
|
// 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(heartBeatEnable && (millis()-heartBeat > ESTOP_SECONDS*1000)) {
|
||||||
if (Diag::WITHROTTLE) DIAG(F("%l WiThrottle(%d) eStop(%ds) timeout, drop connection"), millis(), clientid, ESTOP_SECONDS);
|
if (Diag::WITHROTTLE) DIAG(F("%l WiThrottle(%d) eStop(%ds) timeout"), millis(), clientid, ESTOP_SECONDS);
|
||||||
LOOPLOCOS('*', -1) {
|
if (missedHeartbeatCounter++ > 10) {
|
||||||
if (myLocos[loco].throttle!='\0') {
|
if (Diag::WITHROTTLE) DIAG(F("Too many missed heartbeats, drop connection"));
|
||||||
if (Diag::WITHROTTLE) DIAG(F("%l eStopping cab %d"),millis(),myLocos[loco].cab);
|
delete this;
|
||||||
DCC::setThrottle(myLocos[loco].cab, 1, DCC::getThrottleDirection(myLocos[loco].cab)); // speed 1 is eStop
|
return;
|
||||||
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
|
eStop();
|
||||||
delete this;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
WiThrottle.h
13
WiThrottle.h
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* © 2021 Mike S
|
* © 2021 Mike S
|
||||||
* © 2020-2021 Chris Harlow
|
* © 2020-2021 Chris Harlow
|
||||||
|
* © 2024 Harald Barth
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of Asbelos DCC API
|
* This file is part of Asbelos DCC API
|
||||||
@ -20,7 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef WiThrottle_h
|
#ifndef WiThrottle_h
|
||||||
#define WiThrottle_h
|
#define WiThrottle_h
|
||||||
|
#include "defines.h"
|
||||||
#include "RingStream.h"
|
#include "RingStream.h"
|
||||||
|
|
||||||
struct MYLOCO {
|
struct MYLOCO {
|
||||||
@ -45,9 +46,15 @@ class WiThrottle {
|
|||||||
~WiThrottle();
|
~WiThrottle();
|
||||||
|
|
||||||
static const int MAX_MY_LOCO=10; // maximum number of locos assigned to a single client
|
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_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 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 WiThrottle* firstThrottle;
|
||||||
static int getInt(byte * cmd);
|
static int getInt(byte * cmd);
|
||||||
static int getLocoId(byte * cmd);
|
static int getLocoId(byte * cmd);
|
||||||
@ -62,6 +69,7 @@ class WiThrottle {
|
|||||||
MYLOCO myLocos[MAX_MY_LOCO];
|
MYLOCO myLocos[MAX_MY_LOCO];
|
||||||
bool heartBeatEnable;
|
bool heartBeatEnable;
|
||||||
unsigned long heartBeat;
|
unsigned long heartBeat;
|
||||||
|
uint8_t missedHeartbeatCounter = 0;
|
||||||
bool introSent=false;
|
bool introSent=false;
|
||||||
bool turnoutsSent=false;
|
bool turnoutsSent=false;
|
||||||
bool rosterSent=false;
|
bool rosterSent=false;
|
||||||
@ -75,6 +83,7 @@ class WiThrottle {
|
|||||||
void multithrottle(RingStream * stream, byte * cmd);
|
void multithrottle(RingStream * stream, byte * cmd);
|
||||||
void locoAction(RingStream * stream, byte* aval, char throttleChar, int cab);
|
void locoAction(RingStream * stream, byte* aval, char throttleChar, int cab);
|
||||||
void accessory(RingStream *, byte* cmd);
|
void accessory(RingStream *, byte* cmd);
|
||||||
|
void eStop();
|
||||||
void checkHeartbeat(RingStream * stream);
|
void checkHeartbeat(RingStream * stream);
|
||||||
void markForBroadcast2(int cab);
|
void markForBroadcast2(int cab);
|
||||||
void sendIntro(Print * stream);
|
void sendIntro(Print * stream);
|
||||||
|
Loading…
Reference in New Issue
Block a user