Allow node to enter loop() if transport is NOK
This commit is contained in:
+80
-54
@@ -20,20 +20,25 @@
|
||||
#include "MyTransport.h"
|
||||
|
||||
// SM: transitions and update states
|
||||
static transportState stInit = { stInitTransition, stInitUpdate };
|
||||
static transportState stParent = { stParentTransition, stParentUpdate };
|
||||
static transportState stID = { stIDTransition, stIDUpdate };
|
||||
static transportState stUplink = { stUplinkTransition, stUplinkUpdate };
|
||||
static transportState stReady = { stReadyTransition, stReadyUpdate };
|
||||
static transportState stFailure = { stFailureTransition, stFailureUpdate };
|
||||
static transportState_t stInit = { stInitTransition, stInitUpdate };
|
||||
static transportState_t stParent = { stParentTransition, stParentUpdate };
|
||||
static transportState_t stID = { stIDTransition, stIDUpdate };
|
||||
static transportState_t stUplink = { stUplinkTransition, stUplinkUpdate };
|
||||
static transportState_t stReady = { stReadyTransition, stReadyUpdate };
|
||||
static transportState_t stFailure = { stFailureTransition, stFailureUpdate };
|
||||
|
||||
// transport SM variables
|
||||
static transportSM _transportSM;
|
||||
static transportSM_t _transportSM;
|
||||
|
||||
// transport config
|
||||
transportConfig_t transportConfig;
|
||||
|
||||
// callbacks
|
||||
transportCallback_t transportOk_cb = NULL;
|
||||
|
||||
// global variables
|
||||
extern MyMessage _msg; // incoming message
|
||||
extern MyMessage _msgTmp; // outgoing message
|
||||
extern NodeConfig _nc; // node config
|
||||
|
||||
#if defined(MY_RAM_ROUTING_TABLE_ENABLED)
|
||||
static routingTable _transportRoutingTable; //!< routing table
|
||||
@@ -70,13 +75,10 @@ void stInitTransition(void) {
|
||||
#endif
|
||||
|
||||
// Read node settings (ID, parent ID, GW distance) from EEPROM
|
||||
hwReadConfigBlock((void*)&_nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(NodeConfig));
|
||||
hwReadConfigBlock((void*)&transportConfig, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(transportConfig_t));
|
||||
}
|
||||
|
||||
void stInitUpdate(void) {
|
||||
#if defined(MY_TRANSPORT_DONT_CARE_MODE)
|
||||
TRANSPORT_DEBUG(PSTR("TSM:INIT:TDC\n")); // transport don't care mode
|
||||
#endif
|
||||
// initialise radio
|
||||
if (!transportInit()) {
|
||||
TRANSPORT_DEBUG(PSTR("!TSM:INIT:TSP FAIL\n"));
|
||||
@@ -89,9 +91,9 @@ void stInitUpdate(void) {
|
||||
#if defined(MY_GATEWAY_FEATURE)
|
||||
// Set configuration for gateway
|
||||
TRANSPORT_DEBUG(PSTR("TSM:INIT:GW MODE\n"));
|
||||
_nc.parentNodeId = GATEWAY_ADDRESS;
|
||||
_nc.distance = 0u;
|
||||
_nc.nodeId = GATEWAY_ADDRESS;
|
||||
transportConfig.parentNodeId = GATEWAY_ADDRESS;
|
||||
transportConfig.distanceGW = 0u;
|
||||
transportConfig.nodeId = GATEWAY_ADDRESS;
|
||||
transportSetAddress(GATEWAY_ADDRESS);
|
||||
// GW mode: skip FPAR,ID,UPL states
|
||||
transportSwitchSM(stReady);
|
||||
@@ -99,12 +101,12 @@ void stInitUpdate(void) {
|
||||
if ((uint8_t)MY_NODE_ID != AUTO) {
|
||||
TRANSPORT_DEBUG(PSTR("TSM:INIT:STATID=%d\n"),(uint8_t)MY_NODE_ID);
|
||||
// Set static ID
|
||||
_nc.nodeId = (uint8_t)MY_NODE_ID;
|
||||
transportConfig.nodeId = (uint8_t)MY_NODE_ID;
|
||||
// Save static ID to eeprom (for bootloader)
|
||||
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, (uint8_t)MY_NODE_ID);
|
||||
}
|
||||
// assign ID if set
|
||||
if (_nc.nodeId == AUTO || transportAssignNodeID(_nc.nodeId)) {
|
||||
if (transportConfig.nodeId == AUTO || transportAssignNodeID(transportConfig.nodeId)) {
|
||||
// if node ID valid (>0 and <255), proceed to next state
|
||||
transportSwitchSM(stParent);
|
||||
}
|
||||
@@ -125,14 +127,14 @@ void stParentTransition(void) {
|
||||
#if defined(MY_PARENT_NODE_IS_STATIC)
|
||||
TRANSPORT_DEBUG(PSTR("TSM:FPAR:STATP=%d\n"), (uint8_t)MY_PARENT_NODE_ID); // static parent
|
||||
_transportSM.findingParentNode = false;
|
||||
_nc.distance = 1u; // assumption, CHKUPL:GWDC will update this variable
|
||||
_nc.parentNodeId = (uint8_t)MY_PARENT_NODE_ID;
|
||||
transportConfig.distanceGW = 1u; // assumption, CHKUPL:GWDC will update this variable
|
||||
transportConfig.parentNodeId = (uint8_t)MY_PARENT_NODE_ID;
|
||||
// save parent ID to eeprom (for bootloader)
|
||||
hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, (uint8_t)MY_PARENT_NODE_ID);
|
||||
#else
|
||||
_transportSM.findingParentNode = true;
|
||||
_nc.distance = DISTANCE_INVALID; // Set distance to max and invalidate parent node ID
|
||||
_nc.parentNodeId = AUTO;
|
||||
transportConfig.distanceGW = DISTANCE_INVALID; // Set distance to max and invalidate parent node ID
|
||||
transportConfig.parentNodeId = AUTO;
|
||||
// Broadcast find parent request
|
||||
(void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_REQUEST).set(""));
|
||||
#endif
|
||||
@@ -147,7 +149,7 @@ void stParentUpdate(void) {
|
||||
#else
|
||||
if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS || _transportSM.preferredParentFound) {
|
||||
// timeout or preferred parent found
|
||||
if (_nc.parentNodeId != AUTO) {
|
||||
if (transportConfig.parentNodeId != AUTO) {
|
||||
// parent assigned
|
||||
TRANSPORT_DEBUG(PSTR("TSM:FPAR:OK\n")); // find parent ok
|
||||
_transportSM.findingParentNode = false;
|
||||
@@ -177,7 +179,7 @@ void stParentUpdate(void) {
|
||||
// stID: verify and request ID if necessary
|
||||
void stIDTransition(void) {
|
||||
TRANSPORT_DEBUG(PSTR("TSM:ID\n")); // verify/request node ID
|
||||
if (_nc.nodeId == AUTO) {
|
||||
if (transportConfig.nodeId == AUTO) {
|
||||
// send ID request
|
||||
setIndication(INDICATION_REQ_NODEID);
|
||||
TRANSPORT_DEBUG(PSTR("TSM:ID:REQ\n")); // request node ID
|
||||
@@ -186,7 +188,7 @@ void stIDTransition(void) {
|
||||
}
|
||||
|
||||
void stIDUpdate(void) {
|
||||
if (_nc.nodeId != AUTO) {
|
||||
if (transportConfig.nodeId != AUTO) {
|
||||
// current node ID is valid
|
||||
TRANSPORT_DEBUG(PSTR("TSM:ID:OK\n"));
|
||||
setIndication(INDICATION_GOT_NODEID);
|
||||
@@ -225,9 +227,9 @@ void stUplinkUpdate(void) {
|
||||
// uplink ok, i.e. GW replied
|
||||
TRANSPORT_DEBUG(PSTR("TSM:UPL:OK\n")); // uplink ok
|
||||
//_transportSM.pingActive = false; ==> set false upon receiving I_PONG
|
||||
if (_transportSM.pingResponse != _nc.distance) {
|
||||
TRANSPORT_DEBUG(PSTR("TSM:UPL:DGWC,O=%d,N=%d\n"), _nc.distance, _transportSM.pingResponse); // distance to GW changed
|
||||
_nc.distance = _transportSM.pingResponse;
|
||||
if (_transportSM.pingResponse != transportConfig.distanceGW) {
|
||||
TRANSPORT_DEBUG(PSTR("TSM:UPL:DGWC,O=%d,N=%d\n"), transportConfig.distanceGW, _transportSM.pingResponse); // distance to GW changed
|
||||
transportConfig.distanceGW = _transportSM.pingResponse;
|
||||
}
|
||||
transportSwitchSM(stReady); // proceed to next state
|
||||
}
|
||||
@@ -257,6 +259,11 @@ void stReadyTransition(void) {
|
||||
_transportSM.uplinkOk = true;
|
||||
_transportSM.failureCounter = 0u; // reset failure counter
|
||||
_transportSM.failedUplinkTransmissions = 0u; // reset failed uplink TX counter
|
||||
// callback
|
||||
if (transportOk_cb) {
|
||||
transportOk_cb();
|
||||
}
|
||||
TRANSPORT_DEBUG(PSTR("TSM:READY:PARAM,ID=%d,PAR=%d,DIS=%d\n"), transportConfig.nodeId, transportConfig.parentNodeId, transportConfig.distanceGW);
|
||||
}
|
||||
|
||||
// stReadyUpdate: monitors link
|
||||
@@ -311,7 +318,7 @@ void stFailureUpdate(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void transportSwitchSM(transportState& newState) {
|
||||
void transportSwitchSM(transportState_t& newState) {
|
||||
if (_transportSM.currentState != &newState) {
|
||||
_transportSM.stateRetries = 0u; // state change, reset retry counter
|
||||
_transportSM.currentState = &newState; // change state
|
||||
@@ -386,9 +393,9 @@ bool transportCheckUplink(const bool force) {
|
||||
_transportSM.lastUplinkCheck = hwMillis();
|
||||
TRANSPORT_DEBUG(PSTR("TSF:CKU:OK\n"));
|
||||
// did distance to GW change upstream, eg. re-routing of uplink nodes
|
||||
if (hopsCount != _nc.distance) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:CKU:DGWC,O=%d,N=%d\n"), _nc.distance, hopsCount); // distance to GW changed
|
||||
_nc.distance = hopsCount;
|
||||
if (hopsCount != transportConfig.distanceGW) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:CKU:DGWC,O=%d,N=%d\n"), transportConfig.distanceGW, hopsCount); // distance to GW changed
|
||||
transportConfig.distanceGW = hopsCount;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -401,7 +408,7 @@ bool transportCheckUplink(const bool force) {
|
||||
bool transportAssignNodeID(const uint8_t newNodeId) {
|
||||
// verify if ID valid
|
||||
if (newNodeId != GATEWAY_ADDRESS && newNodeId != AUTO) {
|
||||
_nc.nodeId = newNodeId;
|
||||
transportConfig.nodeId = newNodeId;
|
||||
transportSetAddress(newNodeId);
|
||||
// Write ID to EEPROM
|
||||
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, newNodeId);
|
||||
@@ -411,14 +418,14 @@ bool transportAssignNodeID(const uint8_t newNodeId) {
|
||||
else {
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:SID:FAIL,ID=%d\n"),newNodeId); // ID is invalid, cannot assign ID
|
||||
setIndication(INDICATION_ERR_NET_FULL);
|
||||
_nc.nodeId = AUTO;
|
||||
transportConfig.nodeId = AUTO;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool transportRouteMessage(MyMessage &message) {
|
||||
const uint8_t destination = message.destination;
|
||||
uint8_t route = _nc.parentNodeId; // by default, all traffic is routed via parent node
|
||||
uint8_t route = transportConfig.parentNodeId; // by default, all traffic is routed via parent node
|
||||
|
||||
if (_transportSM.findingParentNode && destination != BROADCAST_ADDRESS) {
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:RTE:FPAR ACTIVE\n")); // find parent active, message not sent
|
||||
@@ -427,7 +434,7 @@ bool transportRouteMessage(MyMessage &message) {
|
||||
}
|
||||
|
||||
if (destination == GATEWAY_ADDRESS) {
|
||||
route = _nc.parentNodeId; // message to GW always routes via parent
|
||||
route = transportConfig.parentNodeId; // message to GW always routes via parent
|
||||
}
|
||||
else if (destination == BROADCAST_ADDRESS) {
|
||||
route = BROADCAST_ADDRESS; // message to BC does not require routing
|
||||
@@ -439,9 +446,9 @@ bool transportRouteMessage(MyMessage &message) {
|
||||
if (route == AUTO) {
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:RTE:%d UNKNOWN\n"), destination); // route unknown
|
||||
#if !defined(MY_GATEWAY_FEATURE)
|
||||
if (message.last != _nc.parentNodeId) {
|
||||
if (message.last != transportConfig.parentNodeId) {
|
||||
// message not from parent, i.e. child node - route it to parent
|
||||
route = _nc.parentNodeId;
|
||||
route = transportConfig.parentNodeId;
|
||||
}
|
||||
else {
|
||||
// route unknown and msg received from parent, send it to destination assuming in rx radius
|
||||
@@ -453,14 +460,14 @@ bool transportRouteMessage(MyMessage &message) {
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
route = _nc.parentNodeId; // not a repeater, all traffic routed via parent
|
||||
route = transportConfig.parentNodeId; // not a repeater, all traffic routed via parent
|
||||
#endif
|
||||
}
|
||||
// send message
|
||||
const bool result = transportSendWrite(route, message);
|
||||
#if !defined(MY_GATEWAY_FEATURE)
|
||||
// update counter
|
||||
if (route == _nc.parentNodeId) {
|
||||
if (route == transportConfig.parentNodeId) {
|
||||
if (!result) {
|
||||
setIndication(INDICATION_ERR_TX);
|
||||
_transportSM.failedUplinkTransmissions++;
|
||||
@@ -506,7 +513,7 @@ bool transportWait(const uint32_t ms, const uint8_t cmd, const uint8_t msgtype){
|
||||
uint8_t transportPingNode(const uint8_t targetId) {
|
||||
if(!_transportSM.pingActive){
|
||||
TRANSPORT_DEBUG(PSTR("TSF:PNG:SEND,TO=%d\n"), targetId);
|
||||
if(targetId == _nc.nodeId) {
|
||||
if(targetId == transportConfig.nodeId) {
|
||||
// pinging self
|
||||
_transportSM.pingResponse = 0u;
|
||||
}
|
||||
@@ -574,7 +581,7 @@ void transportProcessMessage(void) {
|
||||
// update routing table if msg not from parent
|
||||
#if defined(MY_REPEATER_FEATURE)
|
||||
#if !defined(MY_GATEWAY_FEATURE)
|
||||
if (last != _nc.parentNodeId) {
|
||||
if (last != transportConfig.parentNodeId) {
|
||||
#else
|
||||
// GW doesn't have parent
|
||||
{
|
||||
@@ -588,7 +595,7 @@ void transportProcessMessage(void) {
|
||||
_transportSM.msgReceived = true;
|
||||
|
||||
// Is message addressed to this node?
|
||||
if (destination == _nc.nodeId) {
|
||||
if (destination == transportConfig.nodeId) {
|
||||
// prevent buffer overflow by limiting max. possible message length (5 bits=31 bytes max) to MAX_PAYLOAD (25 bytes)
|
||||
mSetLength(_msg, min(mGetLength(_msg),(uint8_t)MAX_PAYLOAD));
|
||||
// null terminate data
|
||||
@@ -599,7 +606,7 @@ void transportProcessMessage(void) {
|
||||
_msgTmp = _msg; // Copy message
|
||||
mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop)
|
||||
mSetAck(_msgTmp, true); // set ACK flag
|
||||
_msgTmp.sender = _nc.nodeId;
|
||||
_msgTmp.sender = transportConfig.nodeId;
|
||||
_msgTmp.destination = sender;
|
||||
// send ACK, use transportSendRoute since ACK reply is not internal, i.e. if !transportOK do not reply
|
||||
(void)transportSendRoute(_msgTmp);
|
||||
@@ -627,15 +634,15 @@ void transportProcessMessage(void) {
|
||||
if (isValidDistance(distance)) {
|
||||
distance++; // Distance to gateway is one more for us w.r.t. parent
|
||||
// update settings if distance shorter or preferred parent found
|
||||
if (((isValidDistance(distance) && distance < _nc.distance) || (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID)) && !_transportSM.preferredParentFound) {
|
||||
if (((isValidDistance(distance) && distance < transportConfig.distanceGW) || (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID)) && !_transportSM.preferredParentFound) {
|
||||
// Found a neighbor closer to GW than previously found
|
||||
if (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID) {
|
||||
_transportSM.preferredParentFound = true;
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR PREF\n")); // find parent, preferred parent found
|
||||
}
|
||||
_nc.distance = distance;
|
||||
_nc.parentNodeId = sender;
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR OK,ID=%d,D=%d\n"), _nc.parentNodeId, _nc.distance);
|
||||
transportConfig.distanceGW = distance;
|
||||
transportConfig.parentNodeId = sender;
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR OK,ID=%d,D=%d\n"), transportConfig.parentNodeId, transportConfig.distanceGW);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -697,7 +704,7 @@ void transportProcessMessage(void) {
|
||||
// only reply if node is fully operational
|
||||
if (type == I_FIND_PARENT_REQUEST) {
|
||||
#if defined(MY_REPEATER_FEATURE)
|
||||
if (sender != _nc.parentNodeId) { // no circular reference
|
||||
if (sender != transportConfig.parentNodeId) { // no circular reference
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR REQ,ID=%d\n"), sender); // FPAR: find parent request
|
||||
// check if uplink functional - node can only be parent node if link to GW functional
|
||||
// this also prevents circular references in case GW ooo
|
||||
@@ -706,7 +713,7 @@ void transportProcessMessage(void) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:GWL OK\n")); // GW uplink ok
|
||||
// random delay minimizes collisions
|
||||
delay(hwMillis() & 0x3ff);
|
||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE).set(_nc.distance));
|
||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE).set(transportConfig.distanceGW));
|
||||
}
|
||||
else {
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:GWL FAIL\n")); // GW uplink fail, do not respond to parent request
|
||||
@@ -721,10 +728,10 @@ void transportProcessMessage(void) {
|
||||
}
|
||||
#if !defined(MY_GATEWAY_FEATURE)
|
||||
if (type == I_DISCOVER_REQUEST) {
|
||||
if (last == _nc.parentNodeId) {
|
||||
if (last == transportConfig.parentNodeId) {
|
||||
// random wait to minimize collisions
|
||||
delay(hwMillis() & 0x3ff);
|
||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_DISCOVER_RESPONSE).set(_nc.parentNodeId));
|
||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_DISCOVER_RESPONSE).set(transportConfig.parentNodeId));
|
||||
// no return here (for fwd if repeater)
|
||||
}
|
||||
}
|
||||
@@ -733,7 +740,7 @@ void transportProcessMessage(void) {
|
||||
// controlled BC relay
|
||||
#if defined(MY_REPEATER_FEATURE)
|
||||
// controlled BC repeating: forward only if message received from parent and sender not self to prevent circular fwds
|
||||
if(last == _nc.parentNodeId && sender != _nc.nodeId && isTransportReady()){
|
||||
if(last == transportConfig.parentNodeId && sender != transportConfig.nodeId && isTransportReady()){
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FWD BC MSG\n")); // controlled broadcast msg forwarding
|
||||
(void)transportRouteMessage(_msg);
|
||||
}
|
||||
@@ -743,7 +750,7 @@ void transportProcessMessage(void) {
|
||||
if (command != C_INTERNAL) {
|
||||
#if !defined(MY_GATEWAY_FEATURE)
|
||||
// only proceed if message received from parent
|
||||
if (last != _nc.parentNodeId) {
|
||||
if (last != transportConfig.parentNodeId) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -818,7 +825,7 @@ void transportProcessFIFO(void) {
|
||||
}
|
||||
|
||||
bool transportSendWrite(const uint8_t to, MyMessage &message) {
|
||||
message.last = _nc.nodeId; // Update last
|
||||
message.last = transportConfig.nodeId; // Update last
|
||||
// sign message if required
|
||||
if (!signerSignMsg(message)) {
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:SIGN FAIL\n"));
|
||||
@@ -842,6 +849,25 @@ bool transportSendWrite(const uint8_t to, MyMessage &message) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void transportRegisterTransportOkCallback(transportCallback_t cb)
|
||||
{
|
||||
transportOk_cb = cb;
|
||||
}
|
||||
|
||||
uint8_t transportGetNodeId(void)
|
||||
{
|
||||
return transportConfig.nodeId;
|
||||
}
|
||||
uint8_t transportGetParentNodeId(void)
|
||||
{
|
||||
return transportConfig.parentNodeId;
|
||||
}
|
||||
uint8_t transportGetDistanceGW(void)
|
||||
{
|
||||
return transportConfig.distanceGW;
|
||||
}
|
||||
|
||||
|
||||
void transportClearRoutingTable(void) {
|
||||
for (uint16_t i = 0; i < SIZE_ROUTES; i++) {
|
||||
transportSetRoute((uint8_t)i, BROADCAST_ADDRESS);
|
||||
|
||||
Reference in New Issue
Block a user