Skip to content

Commit

Permalink
Merge pull request #21 from DCC-EX:isMoving-bugfix
Browse files Browse the repository at this point in the history
IsMoving-bugfix
  • Loading branch information
peteGSX authored Nov 3, 2024
2 parents f784c88 + a28a7ff commit 5c10d80
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 10 deletions.
5 changes: 4 additions & 1 deletion docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Once the `DCCEXProtocol` object is instantiated, a connection must be made to th

It is also recommended to enable logging to an Arduino Stream using the `setLogStream(&stream)` method.

For WiFi clients, long periods of no interactive commands being sent may cause the WiFi client to be disconnected, so it is recommended to enable heartbeats for these, which defaults to sending a heartbeat every 60 seconds. If commands are sent regularly, no heartbeats are sent.

An example using an ESP32 with WiFi to connect to EX-CommandStation, with logging to the serial console:

.. code-block:: cpp
Expand All @@ -34,6 +36,7 @@ An example using an ESP32 with WiFi to connect to EX-CommandStation, with loggin
while(1) delay(1000);
}
dccexProtocol.setLogStream(&Serial);
dccexProtocol.enableHeartbeat();
dccexProtocol.connect(&client);
}
Expand Down Expand Up @@ -100,7 +103,7 @@ All objects are contained within linked lists and can be access via for loops:
// route methods are available here
}
for (Turntable* turntable=dccexProtocol.roster->getFirst(); turntable; turntable=turntable->getNext()) {
for (Turntable* turntable=dccexProtocol.turntables->getFirst(); turntable; turntable=turntable->getNext()) {
// turntable methods are available here
for (TurntableIndex* ttIndex=turntable->getFirstIndex(); ttIndex; ttIndex=ttIndex->getNextIndex()) {
// turntable index methods are available here
Expand Down
2 changes: 2 additions & 0 deletions examples/DCCEXProtocol_Basic/DCCEXProtocol_Basic.ino
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ void setup() {

dccexProtocol.setLogStream(&Serial);

dccexProtocol.enableHeartbeat();

// Pass the communication to wiThrottleProtocol
dccexProtocol.connect(&client);
Serial.println("DCC-EX connected");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ void setup() {
// Pass the delegate instance to wiThrottleProtocol
dccexProtocol.setDelegate(&myDelegate);

dccexProtocol.enableHeartbeat();

// Pass the communication to wiThrottleProtocol
dccexProtocol.connect(&client);
Serial.println("DCC-EX connected");
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=DCCEXProtocol
version=0.0.16
version=0.0.17
author=Peter Cole, Peter Akers <akersp62@gmail.com>
maintainer=Peter Cole, Peter Akers <akersp62@gmail.com>
sentence=DCC-EX Native Protocol implementation
Expand Down
37 changes: 30 additions & 7 deletions src/DCCEXProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,16 @@ DCCEXProtocol::DCCEXProtocol(int maxCmdBuffer) {
DCCEXInbound::setup(MAX_COMMAND_PARAMS);
_cmdBuffer[0] = 0;
_bufflen = 0;

// Set heartbeat defaults
_enableHeartbeat = 0;
_heartbeatDelay = 0;
_lastHeartbeat = 0;
}

DCCEXProtocol::~DCCEXProtocol() {
// Free memory for command buffer
delete[] (_cmdBuffer);
delete[](_cmdBuffer);

// Cleanup command parser
DCCEXInbound::cleanup();
Expand All @@ -76,6 +81,11 @@ void DCCEXProtocol::setDelegate(DCCEXProtocolDelegate *delegate) { this->_delega
// Set the Stream used for logging
void DCCEXProtocol::setLogStream(Stream *console) { this->_console = console; }

void DCCEXProtocol::enableHeartbeat(unsigned long heartbeatDelay) {
_enableHeartbeat = true;
_heartbeatDelay = heartbeatDelay;
}

void DCCEXProtocol::connect(Stream *stream) {
_init();
this->_stream = stream;
Expand Down Expand Up @@ -114,6 +124,9 @@ void DCCEXProtocol::check() {
_bufflen = 0;
}
}
if (_enableHeartbeat) {
_sendHeartbeat();
}
}
}

Expand Down Expand Up @@ -532,7 +545,8 @@ void DCCEXProtocol::_sendCommand() {
_stream->println(_outboundCommand);
_console->print("==> ");
_console->println(_outboundCommand);
*_outboundCommand = 0; // clear it once it has been sent
*_outboundCommand = 0; // clear it once it has been sent
_lastHeartbeat = millis(); // If we sent a command, a heartbeat isn't necessary
}
}

Expand All @@ -547,7 +561,7 @@ void DCCEXProtocol::_processCommand() {
_processScreenUpdate();
}
break;

case 'i': // iDCC-EX server info
if (DCCEXInbound::isTextParameter(0)) {
_processServerDescription();
Expand Down Expand Up @@ -698,7 +712,16 @@ void DCCEXProtocol::_processMessage() { //<m "message">
}

void DCCEXProtocol::_processScreenUpdate() { //<@ screen row "message">
_delegate->receivedScreenUpdate(DCCEXInbound::getNumber(0), DCCEXInbound::getNumber(1), DCCEXInbound::getTextParameter(2));
_delegate->receivedScreenUpdate(DCCEXInbound::getNumber(0), DCCEXInbound::getNumber(1),
DCCEXInbound::getTextParameter(2));
}

void DCCEXProtocol::_sendHeartbeat() {
if (millis() - _lastHeartbeat > _heartbeatDelay) {
_lastHeartbeat = millis();
sprintf(_outboundCommand, "<#>");
_sendCommand();
}
}

// Consist/loco methods
Expand Down Expand Up @@ -1106,17 +1129,17 @@ void DCCEXProtocol::_processTurntableIndexEntry() { // <jP id index angle "[desc
}

void DCCEXProtocol::_processTurntableBroadcast() { // <I id position moving>
// console->println(F("processTurntableAction(): "));
// _console->println(F("_processTurntableBroadcast(): "));
int id = DCCEXInbound::getNumber(0);
int newIndex = DCCEXInbound::getNumber(1);
bool moving = DCCEXInbound::getNumber(2);
Turntable *tt = getTurntableById(id);
if (tt && tt->getIndex() != newIndex) {
if (tt) {
tt->setIndex(newIndex);
tt->setMoving(moving);
}
_delegate->receivedTurntableAction(id, newIndex, moving);
// console->println(F("processTurntableAction(): end"));
// _console->println(F("processTurntableAction(): end"));
}

// Track management methods
Expand Down
11 changes: 11 additions & 0 deletions src/DCCEXProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
/*
Version information:
0.0.17 - Fix typo in turntable example
- Fix bug where the turntable isMoving() method always returned true
- Add enableHeartbeat(heartbeatDelay) to send a heartbeat every x ms if a command is not sent
0.0.16 - add public sendCommand method
0.0.15 - any acquired loco is now retained in the roster
0.0.14 - add getNumberSupportedLocos() used for the fake heartbeat
Expand Down Expand Up @@ -211,6 +214,10 @@ class DCCEXProtocol {
/// @param console
void setLogStream(Stream *console);

/// @brief Enable heartbeat if required - can help WiFi connections that drop out
/// @param heartbeatDelay Time in milliseconds between heartbeats - defaults to one minute (60000ms)
void enableHeartbeat(unsigned long heartbeatDelay = 60000);

/// @brief Connect the stream object to interact with DCC-EX
/// @param stream
void connect(Stream *stream);
Expand Down Expand Up @@ -466,6 +473,7 @@ class DCCEXProtocol {
void _processServerDescription();
void _processMessage();
void _processScreenUpdate();
void _sendHeartbeat();

// Consist/loco methods
void _processLocoBroadcast();
Expand Down Expand Up @@ -538,6 +546,9 @@ class DCCEXProtocol {
bool _receivedRouteList = false; // Flag that route list received
bool _turntableListRequested = false; // Flag that turntable list requested
bool _receivedTurntableList = false; // Flag that turntable list received
bool _enableHeartbeat; // Flag if heartbeat is enabled
unsigned long _heartbeatDelay; // Delay between heartbeats if enabled
unsigned long _lastHeartbeat; // Time in ms of the last heartbeat, also set by sending a command
};

#endif // DCCEXPROTOCOL_H
2 changes: 1 addition & 1 deletion src/DCCEXTurntables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include "DCCEXTurntables.h"
#include <Arduino.h>


// class TurntableIndex

TurntableIndex *TurntableIndex::_first = nullptr;
Expand Down Expand Up @@ -62,6 +61,7 @@ Turntable::Turntable(int id) {
_index = 0;
_numberOfIndexes = 0;
_name = nullptr;
_isMoving = false;
_firstIndex = nullptr;
_indexCount = 0;
_next = nullptr;
Expand Down

0 comments on commit 5c10d80

Please sign in to comment.