Skip to content

Commit c6fb5bf

Browse files
Allow XBeeWithCallbacks::waitFor() to check status responses too
Now, if a frameId is passed, waitFor() will check for status response while waiting. If one is received that matches the frameId and has a non-zero status (e.g. an error), waiting stops and the status is returned. When sending a TX packet and subsequently listening for a RX reply, this allows waiting for a reply and the TX status at the same time and stop waiting if the TX turns out to have failed. This is particularly convenient since the TX status can sometimes arrive *before* the RX reply and sometimes *after*, which makes a sequential waitForStatus() and waitFor() approach not work.
1 parent 4bd4bd7 commit c6fb5bf

File tree

2 files changed

+42
-19
lines changed

2 files changed

+42
-19
lines changed

XBee.cpp

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,11 +1697,19 @@ uint8_t XBeeWithCallbacks::matchStatus(uint8_t frameId) {
16971697
return 0xff;
16981698
}
16991699

1700-
bool XBeeWithCallbacks::waitForInternal(uint8_t apiId, void *response, uint16_t timeout, void *func, uintptr_t data) {
1700+
uint8_t XBeeWithCallbacks::waitForInternal(uint8_t apiId, void *response, uint16_t timeout, void *func, uintptr_t data, int16_t frameId) {
17011701
unsigned long start = millis();
17021702
do {
17031703
// Wait for a packet of the right type
17041704
if (loopTop()) {
1705+
if (frameId >= 0) {
1706+
uint8_t status = matchStatus(frameId);
1707+
// If a status was found, but it was not
1708+
// a zero success status, stop waiting
1709+
if (status != 0xff && status != 0)
1710+
return status;
1711+
}
1712+
17051713
if (getResponse().getApiId() == apiId) {
17061714
// If the type is right, call the right
17071715
// conversion function based on the
@@ -1720,95 +1728,95 @@ bool XBeeWithCallbacks::waitForInternal(uint8_t apiId, void *response, uint16_t
17201728
bool(*f)(ZBTxStatusResponse&,uintptr_t) = (bool(*)(ZBTxStatusResponse&,uintptr_t))func;
17211729
getResponse().getZBTxStatusResponse(*r);
17221730
if(!f || f(*r, data))
1723-
return true;
1731+
return 0;
17241732
break;
17251733
}
17261734
case ZBRxResponse::API_ID: {
17271735
ZBRxResponse *r = (ZBRxResponse*)response;
17281736
bool(*f)(ZBRxResponse&,uintptr_t) = (bool(*)(ZBRxResponse&,uintptr_t))func;
17291737
getResponse().getZBRxResponse(*r);
17301738
if(!f || f(*r, data))
1731-
return true;
1739+
return 0;
17321740
break;
17331741
}
17341742
case ZBExplicitRxResponse::API_ID: {
17351743
ZBExplicitRxResponse *r = (ZBExplicitRxResponse*)response;
17361744
bool(*f)(ZBExplicitRxResponse&,uintptr_t) = (bool(*)(ZBExplicitRxResponse&,uintptr_t))func;
17371745
getResponse().getZBExplicitRxResponse(*r);
17381746
if(!f || f(*r, data))
1739-
return true;
1747+
return 0;
17401748
break;
17411749
}
17421750
case ZBRxIoSampleResponse::API_ID: {
17431751
ZBRxIoSampleResponse *r = (ZBRxIoSampleResponse*)response;
17441752
bool(*f)(ZBRxIoSampleResponse&,uintptr_t) = (bool(*)(ZBRxIoSampleResponse&,uintptr_t))func;
17451753
getResponse().getZBRxIoSampleResponse(*r);
17461754
if(!f || f(*r, data))
1747-
return true;
1755+
return 0;
17481756
break;
17491757
}
17501758
case TxStatusResponse::API_ID: {
17511759
TxStatusResponse *r = (TxStatusResponse*)response;
17521760
bool(*f)(TxStatusResponse&,uintptr_t) = (bool(*)(TxStatusResponse&,uintptr_t))func;
17531761
getResponse().getTxStatusResponse(*r);
17541762
if(!f || f(*r, data))
1755-
return true;
1763+
return 0;
17561764
break;
17571765
}
17581766
case Rx16Response::API_ID: {
17591767
Rx16Response *r = (Rx16Response*)response;
17601768
bool(*f)(Rx16Response&,uintptr_t) = (bool(*)(Rx16Response&,uintptr_t))func;
17611769
getResponse().getRx16Response(*r);
17621770
if(!f || f(*r, data))
1763-
return true;
1771+
return 0;
17641772
break;
17651773
}
17661774
case Rx64Response::API_ID: {
17671775
Rx64Response *r = (Rx64Response*)response;
17681776
bool(*f)(Rx64Response&,uintptr_t) = (bool(*)(Rx64Response&,uintptr_t))func;
17691777
getResponse().getRx64Response(*r);
17701778
if(!f || f(*r, data))
1771-
return true;
1779+
return 0;
17721780
break;
17731781
}
17741782
case Rx16IoSampleResponse::API_ID: {
17751783
Rx16IoSampleResponse *r = (Rx16IoSampleResponse*)response;
17761784
bool(*f)(Rx16IoSampleResponse&,uintptr_t) = (bool(*)(Rx16IoSampleResponse&,uintptr_t))func;
17771785
getResponse().getRx16IoSampleResponse(*r);
17781786
if(!f || f(*r, data))
1779-
return true;
1787+
return 0;
17801788
break;
17811789
}
17821790
case Rx64IoSampleResponse::API_ID: {
17831791
Rx64IoSampleResponse *r = (Rx64IoSampleResponse*)response;
17841792
bool(*f)(Rx64IoSampleResponse&,uintptr_t) = (bool(*)(Rx64IoSampleResponse&,uintptr_t))func;
17851793
getResponse().getRx64IoSampleResponse(*r);
17861794
if(!f || f(*r, data))
1787-
return true;
1795+
return 0;
17881796
break;
17891797
}
17901798
case ModemStatusResponse::API_ID: {
17911799
ModemStatusResponse *r = (ModemStatusResponse*)response;
17921800
bool(*f)(ModemStatusResponse&,uintptr_t) = (bool(*)(ModemStatusResponse&,uintptr_t))func;
17931801
getResponse().getModemStatusResponse(*r);
17941802
if(!f || f(*r, data))
1795-
return true;
1803+
return 0;
17961804
break;
17971805
}
17981806
case AtCommandResponse::API_ID: {
17991807
AtCommandResponse *r = (AtCommandResponse*)response;
18001808
bool(*f)(AtCommandResponse&,uintptr_t) = (bool(*)(AtCommandResponse&,uintptr_t))func;
18011809
getResponse().getAtCommandResponse(*r);
18021810
if(!f || f(*r, data))
1803-
return true;
1811+
return 0;
18041812
break;
18051813
}
18061814
case RemoteAtCommandResponse::API_ID: {
18071815
RemoteAtCommandResponse *r = (RemoteAtCommandResponse*)response;
18081816
bool(*f)(RemoteAtCommandResponse&,uintptr_t) = (bool(*)(RemoteAtCommandResponse&,uintptr_t))func;
18091817
getResponse().getRemoteAtCommandResponse(*r);
18101818
if(!f || f(*r, data))
1811-
return true;
1819+
return 0;
18121820
break;
18131821
}
18141822
}
@@ -1817,7 +1825,7 @@ bool XBeeWithCallbacks::waitForInternal(uint8_t apiId, void *response, uint16_t
18171825
loopBottom();
18181826
}
18191827
} while (millis() - start < timeout);
1820-
return false;
1828+
return XBEE_WAIT_TIMEOUT;
18211829
}
18221830

18231831
uint8_t XBeeWithCallbacks::waitForStatus(uint8_t frameId, uint16_t timeout) {

XBee.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -895,9 +895,24 @@ class XBeeWithCallbacks : public XBee {
895895
* of the right type received, passing the response and the data
896896
* parameter passed to this method. If the function returns true
897897
* (or if no function was passed), waiting stops and this method
898-
* returns true. If the function returns false, waiting
898+
* returns 0. If the function returns false, waiting
899899
* continues. After the given timeout passes, this method
900-
* returns false.
900+
* returns XBEE_WAIT_TIMEOUT.
901+
*
902+
* If a valid frameId is passed (e.g. 0-255 inclusive) and a
903+
* status API response frame is received while waiting, that has
904+
* a *non-zero* status, waiting stops and that status is
905+
* received. This is intended for when a TX packet was sent and
906+
* you are waiting for an RX reply, which will most likely never
907+
* arrive when TX failed. However, since the status reply is not
908+
* guaranteed to arrive before the RX reply (a remote module can
909+
* send a reply before the ACK), first calling waitForStatus()
910+
* and then waitFor() can sometimes miss the reply RX packet.
911+
*
912+
* Note that when the intended response is received *before* the
913+
* status reply, the latter will not be processed by this
914+
* method and will be subsequently processed by e.g. loop()
915+
* normally.
901916
*
902917
* While waiting, any other responses received are passed to the
903918
* relevant callbacks, just as if calling loop() continuously
@@ -908,8 +923,8 @@ class XBeeWithCallbacks : public XBee {
908923
* retrieved using getResponse() as normal.
909924
*/
910925
template <typename Response>
911-
bool waitFor(Response& response, uint16_t timeout, bool (*func)(Response&, uintptr_t) = NULL, uintptr_t data = 0) {
912-
return waitForInternal(Response::API_ID, &response, timeout, (void*)func, data);
926+
uint8_t waitFor(Response& response, uint16_t timeout, bool (*func)(Response&, uintptr_t) = NULL, uintptr_t data = 0, int16_t frameId = -1) {
927+
return waitForInternal(Response::API_ID, &response, timeout, (void*)func, data, frameId);
913928
}
914929

915930
/**
@@ -950,7 +965,7 @@ class XBeeWithCallbacks : public XBee {
950965
* function to the corresponding type. This means that the
951966
* void* given must match the api id!
952967
*/
953-
bool waitForInternal(uint8_t apiId, void *response, uint16_t timeout, void *func, uintptr_t data);
968+
uint8_t waitForInternal(uint8_t apiId, void *response, uint16_t timeout, void *func, uintptr_t data, int16_t frameId);
954969

955970
/**
956971
* Helper that checks if the current response is a status

0 commit comments

Comments
 (0)