14
14
#include " utility/RF24.h"
15
15
#include " utility/RF24_config.h"
16
16
17
- #define DISTANCE_INVALID (0xFF )
18
-
19
17
20
18
// Inline function and macros
21
- static inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) {
19
+ inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) {
22
20
msg.sender = sender;
23
21
msg.destination = destination;
24
22
msg.sensor = sensor;
@@ -29,13 +27,6 @@ static inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destinat
29
27
return msg;
30
28
}
31
29
32
- static inline bool isValidParent ( const uint8_t parent ) {
33
- return parent != AUTO;
34
- }
35
- static inline bool isValidDistance ( const uint8_t distance ) {
36
- return distance != DISTANCE_INVALID;
37
- }
38
-
39
30
40
31
MySensor::MySensor (uint8_t _cepin, uint8_t _cspin) : RF24(_cepin, _cspin) {
41
32
}
@@ -46,7 +37,6 @@ void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, b
46
37
isGateway = false ;
47
38
repeaterMode = _repeaterMode;
48
39
msgCallback = _msgCallback;
49
- failedTransmissions = 0 ;
50
40
51
41
if (repeaterMode) {
52
42
setupRepeaterMode ();
@@ -62,26 +52,29 @@ void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, b
62
52
cc.isMetric = 0x01 ;
63
53
}
64
54
65
- autoFindParent = _parentNodeId == AUTO;
66
- if (!autoFindParent) {
55
+ if (_parentNodeId != AUTO) {
67
56
nc.parentNodeId = _parentNodeId;
68
- nc.distance = 0 ;
69
- } else if (!isValidParent (nc.parentNodeId )) {
70
- // Auto find parent, but parent in eeprom is invalid. Force parent search on first transmit.
71
- nc.distance = DISTANCE_INVALID;
57
+ autoFindParent = false ;
58
+ } else {
59
+ autoFindParent = true ;
72
60
}
73
61
74
62
if (_nodeId != AUTO) {
75
63
// Set static id
76
64
nc.nodeId = _nodeId;
77
65
}
78
66
67
+ // If no parent was found in eeprom. Try to find one.
68
+ if (autoFindParent && nc.parentNodeId == 0xff ) {
69
+ findParentNode ();
70
+ }
71
+
79
72
// Try to fetch node-id from gateway
80
73
if (nc.nodeId == AUTO) {
81
74
requestNodeId ();
82
75
}
83
76
84
- debug (PSTR (" %s started, id=%d, parent=%d, distance=%d \n " ), repeaterMode?" repeater" :" sensor" , nc.nodeId , nc. parentNodeId , nc. distance );
77
+ debug (PSTR (" %s started, id %d \n " ), repeaterMode?" repeater" :" sensor" , nc.nodeId );
85
78
86
79
// Open reading pipe for messages directed to this node (set write pipe to same)
87
80
RF24::openReadingPipe (WRITE_PIPE, TO_ADDR (nc.nodeId ));
@@ -100,6 +93,8 @@ void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, b
100
93
}
101
94
102
95
void MySensor::setupRadio (rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate) {
96
+ failedTransmissions = 0 ;
97
+
103
98
// Start up the radio library
104
99
RF24::begin ();
105
100
@@ -109,13 +104,13 @@ void MySensor::setupRadio(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_
109
104
}
110
105
RF24::setAutoAck (1 );
111
106
RF24::setAutoAck (BROADCAST_PIPE,false ); // Turn off auto ack for broadcast
107
+ RF24::enableAckPayload ();
112
108
RF24::setChannel (channel);
113
109
RF24::setPALevel (paLevel);
114
110
RF24::setDataRate (dataRate);
115
111
RF24::setRetries (5 ,15 );
116
112
RF24::setCRCLength (RF24_CRC_16);
117
113
RF24::enableDynamicPayloads ();
118
- RF24::enableDynamicAck ();// Required to disable ack-sending for broadcast messages
119
114
120
115
// All nodes listen to broadcast pipe (for FIND_PARENT_RESPONSE messages)
121
116
RF24::openReadingPipe (BROADCAST_PIPE, TO_ADDR (BROADCAST_ADDRESS));
@@ -144,12 +139,14 @@ void MySensor::requestNodeId() {
144
139
145
140
146
141
void MySensor::findParentNode () {
147
- // Send ping message to BROADCAST_ADDRESS (to which all relaying nodes and gateway listens and should reply to)
148
- debug (PSTR (" find parent\n " ));
142
+ failedTransmissions = 0 ;
149
143
144
+ // Set distance to max
145
+ nc.distance = 255 ;
146
+
147
+ // Send ping message to BROADCAST_ADDRESS (to which all relaying nodes and gateway listens and should reply to)
150
148
build (msg, nc.nodeId , BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT, false ).set (" " );
151
- // Write msg, but suppress recursive parent search
152
- sendWrite (BROADCAST_ADDRESS, msg, false );
149
+ sendWrite (BROADCAST_ADDRESS, msg, true );
153
150
154
151
// Wait for ping response.
155
152
waitForReply ();
@@ -185,64 +182,44 @@ boolean MySensor::sendRoute(MyMessage &message) {
185
182
} else if (isInternal && message.type == I_ID_RESPONSE && dest==BROADCAST_ADDRESS) {
186
183
// Node has not yet received any id. We need to send it
187
184
// by doing a broadcast sending,
188
- return sendWrite (BROADCAST_ADDRESS, message);
185
+ return sendWrite (BROADCAST_ADDRESS, message, true );
189
186
}
190
187
}
191
188
192
189
if (!isGateway) {
190
+ // --- debug(PSTR("route parent\n"));
193
191
// Should be routed back to gateway.
194
- return sendWrite (nc.parentNodeId , message);
192
+ bool ok = sendWrite (nc.parentNodeId , message);
193
+
194
+ if (!ok) {
195
+ // Failure when sending to parent node. The parent node might be down and we
196
+ // need to find another route to gateway.
197
+ if (autoFindParent && failedTransmissions > SEARCH_FAILURES) {
198
+ findParentNode ();
199
+ }
200
+ failedTransmissions++;
201
+ } else {
202
+ failedTransmissions = 0 ;
203
+ }
204
+ return ok;
195
205
}
196
206
return false ;
197
207
}
198
208
199
- boolean MySensor::sendWrite (uint8_t next, MyMessage &message, const bool allowFindParent) {
200
- bool ok = true ;
201
- const bool broadcast = next == BROADCAST_ADDRESS;
202
- const bool toParent = next == nc.parentNodeId ;
203
- // With current implementation parent node Id can equal the broadcast address when
204
- // starting with empty eeprom and AUTO node Id is active.
205
- // This behavior is undesired, as possible parents will report back to broadcast address.
206
- // debug(PSTR("sendWrite next=%d, parent=%d, distance=%d\n"), next, nc.parentNodeId, nc.distance);
207
- // If sending directly to parent node and distance is not set, then try to find parent now.
208
- if ( allowFindParent && toParent && !isValidDistance (nc.distance ) ) {
209
- findParentNode ();
210
- // Known distance indicates parent has been found
211
- ok = isValidDistance (nc.distance );
212
- }
209
+ boolean MySensor::sendWrite (uint8_t next, MyMessage &message, bool broadcast) {
210
+ uint8_t length = mGetLength (message);
211
+ message.last = nc.nodeId ;
212
+ mSetVersion (message, PROTOCOL_VERSION);
213
+ // Make sure radio has powered up
214
+ RF24::powerUp ();
215
+ RF24::stopListening ();
216
+ RF24::openWritingPipe (TO_ADDR (next));
217
+ bool ok = RF24::write (&message, min (MAX_MESSAGE_LENGTH, HEADER_SIZE + length), broadcast);
218
+ RF24::startListening ();
219
+
220
+ debug (PSTR (" send: %d-%d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,st=%s:%s\n " ),
221
+ message.sender ,message.last , next, message.destination , message.sensor , mGetCommand (message), message.type , mGetPayloadType (message), mGetLength (message), ok?" ok" :" fail" , message.getString (convBuf));
213
222
214
- if (ok) {
215
- uint8_t length = mGetLength (message);
216
- message.last = nc.nodeId ;
217
- mSetVersion (message, PROTOCOL_VERSION);
218
- // Make sure radio has powered up
219
- RF24::powerUp ();
220
- RF24::stopListening ();
221
- RF24::openWritingPipe (TO_ADDR (next));
222
- // Send message. Disable auto-ack for broadcasts.
223
- ok = RF24::write (&message, min (MAX_MESSAGE_LENGTH, HEADER_SIZE + length), broadcast);
224
- RF24::startListening ();
225
-
226
- debug (PSTR (" send: %d-%d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,st=%s:%s\n " ),
227
- message.sender ,message.last , next, message.destination , message.sensor , mGetCommand (message), message.type ,
228
- mGetPayloadType (message), mGetLength (message), broadcast ? " bc" : (ok ? " ok" :" fail" ), message.getString (convBuf));
229
-
230
- // If many successive transmissions to parent failed, the parent node might be down and we
231
- // need to find another route to gateway.
232
- if (toParent) {
233
- if (ok) {
234
- failedTransmissions = 0 ;
235
- } else {
236
- failedTransmissions++;
237
- if ( autoFindParent && (failedTransmissions >= SEARCH_FAILURES)) {
238
- debug (PSTR (" lost parent\n " ));
239
- // Set distance invalid to trigger parent search on next write.
240
- nc.distance = DISTANCE_INVALID;
241
- failedTransmissions = 0 ;
242
- }
243
- }
244
- }
245
- }
246
223
return ok;
247
224
}
248
225
@@ -290,7 +267,7 @@ boolean MySensor::process() {
290
267
291
268
uint8_t len = RF24::getDynamicPayloadSize ();
292
269
RF24::read (&msg, len);
293
- // RF24::writeAckPayload(pipe,&pipe, 1 );
270
+ RF24::writeAckPayload (pipe,&pipe, 1 );
294
271
295
272
// Add string termination, good if we later would want to print it.
296
273
msg.data [mGetLength (msg)] = ' \0 ' ;
@@ -310,10 +287,10 @@ boolean MySensor::process() {
310
287
311
288
if (repeaterMode && command == C_INTERNAL && type == I_FIND_PARENT) {
312
289
// Relaying nodes should always answer ping messages
313
- // Wait a random delay of 0-1.023 seconds to minimize collision
290
+ // Wait a random delay of 0-2 seconds to minimize collision
314
291
// between ping ack messages from other relaying nodes
315
292
delay (millis () & 0x3ff );
316
- sendWrite (sender, build (msg, nc.nodeId , sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE, false ).set (nc.distance ));
293
+ sendWrite (sender, build (msg, nc.nodeId , sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE, false ).set (nc.distance ), true );
317
294
return false ;
318
295
} else if (destination == nc.nodeId ) {
319
296
// Check if sender requests an ack back.
@@ -338,18 +315,13 @@ boolean MySensor::process() {
338
315
// We've received a reply to a FIND_PARENT message. Check if the distance is
339
316
// shorter than we already have.
340
317
uint8_t distance = msg.getByte ();
341
- if (isValidDistance (distance))
342
- {
343
- // Distance to gateway is one more for us w.r.t. parent
344
- distance++;
345
- if (isValidDistance (distance) && (distance < nc.distance )) {
346
- // Found a neighbor closer to GW than previously found
347
- nc.distance = distance;
348
- nc.parentNodeId = msg.sender ;
349
- eeprom_write_byte ((uint8_t *)EEPROM_PARENT_NODE_ID_ADDRESS, nc.parentNodeId );
350
- eeprom_write_byte ((uint8_t *)EEPROM_DISTANCE_ADDRESS, nc.distance );
351
- debug (PSTR (" new parent=%d, d=%d\n " ), nc.parentNodeId , nc.distance );
352
- }
318
+ if (distance<nc.distance -1 ) {
319
+ // Found a neighbor closer to GW than previously found
320
+ nc.distance = distance + 1 ;
321
+ nc.parentNodeId = msg.sender ;
322
+ eeprom_write_byte ((uint8_t *)EEPROM_PARENT_NODE_ID_ADDRESS, nc.parentNodeId );
323
+ eeprom_write_byte ((uint8_t *)EEPROM_DISTANCE_ADDRESS, nc.distance );
324
+ debug (PSTR (" new parent=%d, d=%d\n " ), nc.parentNodeId , nc.distance );
353
325
}
354
326
return false ;
355
327
} else if (sender == GATEWAY_ADDRESS) {
0 commit comments