Skip to content

Commit 470bff4

Browse files
Add a bunch of printing callback functions
These functions can be used as callbacks for XBeeWithCallback and print various packets. printErrorCb() can easily print errors to simplify sketches. printRawResponseCb() and printResponseCb() print complete responses and will be mostly useful for debugging (especially the generic printResponseCb() version is fairly big due to all the strings, it compiles to around 5.5k).
1 parent 0da629f commit 470bff4

File tree

2 files changed

+372
-0
lines changed

2 files changed

+372
-0
lines changed

Printers.cpp

Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,336 @@ void printHex(Print& p, const uint8_t* buf, size_t len, const __FlashStringHelpe
2121
cur_group++;
2222
}
2323
}
24+
25+
void printErrorCb(uint8_t code, uintptr_t data) {
26+
Print *p = (Print*)data;
27+
p->print(F("Error reading API packet. Error code: "));
28+
p->println(code);
29+
}
30+
31+
void printErrorCb(ZBTxStatusResponse& r, uintptr_t data) {
32+
Print *p = (Print*)data;
33+
if (!r.isSuccess()) {
34+
p->print(F("Error sending Zigbee packet. Delivery status: "));
35+
p->println(r.getDeliveryStatus());
36+
}
37+
}
38+
39+
void printErrorCb(TxStatusResponse& r, uintptr_t data) {
40+
Print *p = (Print*)data;
41+
if (!r.isSuccess()) {
42+
p->print(F("Error sending packet. Delivery status: "));
43+
p->println(r.getStatus());
44+
}
45+
}
46+
47+
void printErrorCb(AtCommandResponse& r, uintptr_t data) {
48+
Print *p = (Print*)data;
49+
if (!r.isOk()) {
50+
p->print(F("Error sending "));
51+
p->write(r.getCommand(), 2);
52+
p->print(F(" command. Status: "));
53+
p->println(r.getStatus());
54+
}
55+
}
56+
57+
void printErrorCb(RemoteAtCommandResponse& r, uintptr_t data) {
58+
Print *p = (Print*)data;
59+
if (!r.isOk()) {
60+
p->print(F("Error sending remote "));
61+
p->write(r.getCommand(), 2);
62+
p->print(F(" command. Status: "));
63+
p->println(r.getStatus());
64+
}
65+
}
66+
67+
void printErrorCb(XBeeResponse& r, uintptr_t data) {
68+
uint8_t id = r.getApiId();
69+
// Figure out the API type and call the corresonding function
70+
if (id == ZB_TX_STATUS_RESPONSE) {
71+
ZBTxStatusResponse response;
72+
r.getZBTxStatusResponse(response);
73+
printErrorCb(response, data);
74+
} else if (id == TX_STATUS_RESPONSE) {
75+
TxStatusResponse response;
76+
r.getTxStatusResponse(response);
77+
printErrorCb(response, data);
78+
} else if (id == AT_COMMAND_RESPONSE) {
79+
AtCommandResponse response;
80+
r.getAtCommandResponse(response);
81+
printErrorCb(response, data);
82+
} else if (id == REMOTE_AT_COMMAND_RESPONSE) {
83+
RemoteAtCommandResponse response;
84+
r.getRemoteAtCommandResponse(response);
85+
printErrorCb(response, data);
86+
}
87+
}
88+
89+
90+
91+
void printRawResponseCb(XBeeResponse& response, uintptr_t data) {
92+
Print *p = (Print*)data;
93+
p->print("Response received: ");
94+
// Reconstruct the original packet
95+
uint8_t header[] = {START_BYTE, response.getMsbLength(), response.getLsbLength(), response.getApiId()};
96+
printHex(*p, header, sizeof(header), F(" "), NULL);
97+
p->write(' ');
98+
printHex(*p, response.getFrameData(), response.getFrameDataLength(), F(" "), NULL);
99+
p->println();
100+
}
101+
102+
103+
104+
/**
105+
* Helper function to print a field name, followed by the hexadecimal
106+
* value and a newline.
107+
*/
108+
template <typename T>
109+
static void printField(Print* p, const __FlashStringHelper *prefix, T data) {
110+
p->print(prefix);
111+
printHex(*p, data);
112+
p->println();
113+
}
114+
115+
void printResponseCb(ZBTxStatusResponse& status, uintptr_t data) {
116+
Print *p = (Print*)data;
117+
p->println(F("ZBTxStatusResponse received:"));
118+
printField(p, F(" FrameId: 0x"), status.getFrameId());
119+
printField(p, F(" To: 0x"), status.getRemoteAddress());
120+
printField(p, F(" Delivery status: 0x"), status.getDeliveryStatus());
121+
printField(p, F(" Discovery status: 0x"), status.getDiscoveryStatus());
122+
}
123+
124+
void printResponseCb(ZBRxResponse& rx, uintptr_t data) {
125+
Print *p = (Print*)data;
126+
p->println(F("ZBRxResponse received:"));
127+
printField(p, F(" From: 0x"), rx.getRemoteAddress64());
128+
printField(p, F(" From: 0x"), rx.getRemoteAddress16());
129+
printField(p, F(" Receive options: 0x"), rx.getOption());
130+
if (rx.getDataLength() > 8)
131+
p->print(" Payload:\r\n ");
132+
else
133+
p->print(" Payload: ");
134+
printHex(*p, rx.getFrameData() + rx.getDataOffset(), rx.getDataLength(), F(" "), F("\r\n "), 8);
135+
p->println();
136+
}
137+
138+
void printResponseCb(ZBExplicitRxResponse& rx, uintptr_t data) {
139+
Print *p = (Print*)data;
140+
p->println(F("ZBExplicitRxResponse received:"));
141+
printField(p, F(" From: 0x"), rx.getRemoteAddress64());
142+
printField(p, F(" From: 0x"), rx.getRemoteAddress16());
143+
printField(p, F(" Receive options: 0x"), rx.getOption());
144+
printField(p, F(" Src endpoint: 0x"), rx.getSrcEndpoint());
145+
printField(p, F(" Dst endpoint: 0x"), rx.getDstEndpoint());
146+
printField(p, F(" Cluster id: 0x"), rx.getClusterId());
147+
printField(p, F(" Profile id: 0x"), rx.getProfileId());
148+
if (rx.getDataLength() > 8)
149+
p->print(" Payload:\r\n ");
150+
else
151+
p->print(" Payload: ");
152+
printHex(*p, rx.getFrameData() + rx.getDataOffset(), rx.getDataLength(), F(" "), F("\r\n "), 8);
153+
p->println();
154+
}
155+
156+
void printResponseCb(ZBRxIoSampleResponse& rx, uintptr_t data) {
157+
Print *p = (Print*)data;
158+
p->println(F("ZBRxIoSampleResponse received:"));
159+
printField(p, F(" From: 0x"), rx.getRemoteAddress64());
160+
printField(p, F(" From: 0x"), rx.getRemoteAddress16());
161+
printField(p, F(" Receive options: 0x"), rx.getOption());
162+
for (uint8_t i = 0; i < 16; ++i) {
163+
if (rx.isDigitalEnabled(i)) {
164+
p->print(F(" Digital pin "));
165+
p->print(i);
166+
p->print(F(": "));
167+
p->print(rx.isDigitalOn(i) ? "HIGH" : "LOW");
168+
p->println();
169+
}
170+
}
171+
for (uint8_t i = 0; i < 8; ++i) {
172+
if (rx.isAnalogEnabled(i)) {
173+
p->print(F(" Analog pin "));
174+
p->print(i);
175+
p->print(F(": 0x"));
176+
printHex(*p, rx.getAnalog(i));
177+
p->println();
178+
}
179+
}
180+
}
181+
182+
void printResponseCb(TxStatusResponse& status, uintptr_t data) {
183+
Print *p = (Print*)data;
184+
p->println(F("TxStatusResponse received:"));
185+
printField(p, F(" FrameId: 0x"), status.getFrameId());
186+
printField(p, F(" Status: 0x"), status.getStatus());
187+
}
188+
189+
void printResponseCb(Rx16Response& rx, uintptr_t data) {
190+
Print *p = (Print*)data;
191+
p->println("Rx16Response received:");
192+
printField(p, F(" From: 0x"), rx.getRemoteAddress16());
193+
printField(p, F(" Rssi: 0x"), rx.getRssi());
194+
printField(p, F(" Receive options: 0x"), rx.getOption());
195+
if (rx.getDataLength() > 8)
196+
p->print(" Payload:\r\n ");
197+
else
198+
p->print(" Payload: ");
199+
printHex(*p, rx.getFrameData() + rx.getDataOffset(), rx.getDataLength(), F(" "), F("\r\n "), 8);
200+
p->println();
201+
}
202+
203+
void printResponseCb(Rx64Response& rx, uintptr_t data) {
204+
Print *p = (Print*)data;
205+
p->println("Rx64Response received:");
206+
printField(p, F(" From: 0x"), rx.getRemoteAddress64());
207+
printField(p, F(" Rssi: 0x"), rx.getRssi());
208+
printField(p, F(" Receive options: 0x"), rx.getOption());
209+
if (rx.getDataLength() > 8)
210+
p->print(" Payload:\r\n ");
211+
else
212+
p->print(" Payload: ");
213+
printHex(*p, rx.getFrameData() + rx.getDataOffset(), rx.getDataLength(), F(" "), F("\r\n "), 8);
214+
p->println();
215+
}
216+
217+
/**
218+
* Helper function to share common functionality between the two sample
219+
* resonses.
220+
*/
221+
static void printSamples(Print* p, RxIoSampleBaseResponse& rx) {
222+
for (uint8_t s = 0; s < rx.getSampleSize(); ++s) {
223+
p->print(F(" Sample "));
224+
p->print(s);
225+
p->println(F(":"));
226+
227+
for (uint8_t i = 0; i < 9; ++i) {
228+
if (rx.isDigitalEnabled(i)) {
229+
p->print(F(" Digital pin "));
230+
p->print(i);
231+
p->print(F(": "));
232+
p->print(rx.isDigitalOn(i, s) ? "HIGH" : "LOW");
233+
p->println();
234+
}
235+
}
236+
for (uint8_t i = 0; i < 7; ++i) {
237+
if (rx.isAnalogEnabled(i)) {
238+
p->print(F(" Analog pin "));
239+
p->print(i);
240+
p->print(F(": 0x"));
241+
printHex(*p, rx.getAnalog(i, s));
242+
p->println();
243+
}
244+
}
245+
}
246+
}
247+
248+
void printResponseCb(Rx16IoSampleResponse& rx, uintptr_t data) {
249+
Print *p = (Print*)data;
250+
p->println("Rx16IoSampleResponse received:");
251+
printField(p, F(" From: 0x"), rx.getRemoteAddress16());
252+
printField(p, F(" Rssi: 0x"), rx.getRssi());
253+
printField(p, F(" Receive options: 0x"), rx.getOption());
254+
printField(p, F(" Number of samples: 0x"), rx.getSampleSize());
255+
printSamples(p, rx);
256+
}
257+
258+
void printResponseCb(Rx64IoSampleResponse& rx, uintptr_t data) {
259+
Print *p = (Print*)data;
260+
p->println("Rx64IoSampleResponse received:");
261+
printField(p, F(" From: 0x"), rx.getRemoteAddress64());
262+
printField(p, F(" Rssi: 0x"), rx.getRssi());
263+
printField(p, F(" Receive options: 0x"), rx.getOption());
264+
printField(p, F(" Number of samples: 0x"), rx.getSampleSize());
265+
printSamples(p, rx);
266+
}
267+
268+
void printResponseCb(ModemStatusResponse& status, uintptr_t data) {
269+
Print *p = (Print*)data;
270+
p->println("ModemStatusResponse received:");
271+
printField(p, F(" Status: 0x"), status.getStatus());
272+
}
273+
274+
void printResponseCb(AtCommandResponse& at, uintptr_t data) {
275+
Print *p = (Print*)data;
276+
p->println("AtCommandResponse received:");
277+
p->print(F(" Command: "));
278+
p->write(at.getCommand(), 2);
279+
p->println();
280+
printField(p, F(" Status: 0x"), at.getStatus());
281+
if (at.getValueLength()) {
282+
p->print(F(" Value: "));
283+
printHex(*p, at.getValue(), at.getValueLength(), F(" "), NULL);
284+
p->println();
285+
}
286+
}
287+
288+
void printResponseCb(RemoteAtCommandResponse& at, uintptr_t data) {
289+
Print *p = (Print*)data;
290+
p->println("AtRemoteCommandResponse received:");
291+
printField(p, F(" To: 0x"), at.getRemoteAddress64());
292+
printField(p, F(" To: 0x"), at.getRemoteAddress16());
293+
p->print(F(" Command: "));
294+
p->write(at.getCommand(), 2);
295+
p->println();
296+
printField(p, F(" Status: 0x"), at.getStatus());
297+
if (at.getValueLength()) {
298+
p->print(F(" Value: "));
299+
printHex(*p, at.getValue(), at.getValueLength(), F(" "), NULL);
300+
p->println();
301+
}
302+
}
303+
304+
void printResponseCb(XBeeResponse& r, uintptr_t data) {
305+
uint8_t id = r.getApiId();
306+
// Figure out the API type and call the corresonding function
307+
if (id == ZB_TX_STATUS_RESPONSE) {
308+
ZBTxStatusResponse response;
309+
r.getZBTxStatusResponse(response);
310+
printResponseCb(response, data);
311+
} else if (id == ZB_RX_RESPONSE) {
312+
ZBRxResponse response;
313+
r.getZBRxResponse(response);
314+
printResponseCb(response, data);
315+
} else if (id == ZB_EXPLICIT_RX_RESPONSE) {
316+
ZBExplicitRxResponse response;
317+
r.getZBExplicitRxResponse(response);
318+
printResponseCb(response, data);
319+
} else if (id == ZB_IO_SAMPLE_RESPONSE) {
320+
ZBRxIoSampleResponse response;
321+
r.getZBRxIoSampleResponse(response);
322+
printResponseCb(response, data);
323+
} else if (id == TX_STATUS_RESPONSE) {
324+
TxStatusResponse response;
325+
r.getTxStatusResponse(response);
326+
printResponseCb(response, data);
327+
} else if (id == RX_16_RESPONSE) {
328+
Rx16Response response;
329+
r.getRx16Response(response);
330+
printResponseCb(response, data);
331+
} else if (id == RX_64_RESPONSE) {
332+
Rx64Response response;
333+
r.getRx64Response(response);
334+
printResponseCb(response, data);
335+
} else if (id == RX_16_IO_RESPONSE) {
336+
Rx16IoSampleResponse response;
337+
r.getRx16IoSampleResponse(response);
338+
printResponseCb(response, data);
339+
} else if (id == RX_64_IO_RESPONSE) {
340+
Rx64IoSampleResponse response;
341+
r.getRx64IoSampleResponse(response);
342+
printResponseCb(response, data);
343+
} else if (id == MODEM_STATUS_RESPONSE) {
344+
ModemStatusResponse response;
345+
r.getModemStatusResponse(response);
346+
printResponseCb(response, data);
347+
} else if (id == AT_COMMAND_RESPONSE) {
348+
AtCommandResponse response;
349+
r.getAtCommandResponse(response);
350+
printResponseCb(response, data);
351+
} else if (id == REMOTE_AT_COMMAND_RESPONSE) {
352+
RemoteAtCommandResponse response;
353+
r.getRemoteAtCommandResponse(response);
354+
printResponseCb(response, data);
355+
}
356+
}

Printers.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,43 @@ inline void printHex(Print& p, XBeeAddress64 v) {
8585
printHex(p, v.getLsb());
8686
}
8787

88+
// The following functions are intended to be used as callbacks, to
89+
// print various information about received responses. All of the
90+
// require a Print* to be passed as the data parameter. For example, to
91+
// print to Serial any TxStatusResponses that contain errors, do:
92+
//
93+
// xbee.onTxStatusResponse(printErrorCb, (uintptr_t)(Print*)&Serial);
94+
//
95+
// Most of these callbacks can either be used as a response-specific
96+
// callback, to only work that specific API response type, or as a
97+
// generic callback (onResponse or onOtherResponse), in which case the
98+
// relevant version of the callback will be called automatically.
99+
100+
// printErrorCb prints any error messages in status responses.
101+
void printErrorCb(uint8_t code, uintptr_t data);
102+
void printErrorCb(ZBTxStatusResponse& r, uintptr_t data);
103+
void printErrorCb(TxStatusResponse& r, uintptr_t data);
104+
void printErrorCb(AtCommandResponse& r, uintptr_t data);
105+
void printErrorCb(RemoteAtCommandResponse& r, uintptr_t data);
106+
void printErrorCb(XBeeResponse& r, uintptr_t data);
107+
108+
// printRawResponseCb prints the raw bytes of a response.
109+
void printRawResponseCb(XBeeResponse& response, uintptr_t data);
110+
111+
// printResponseCb prints a human-readable version of a response, showing
112+
// the values of all fields individually.
113+
void printResponseCb(ZBTxStatusResponse& status, uintptr_t data);
114+
void printResponseCb(ZBRxResponse& rx, uintptr_t data);
115+
void printResponseCb(ZBExplicitRxResponse& rx, uintptr_t data);
116+
void printResponseCb(ZBRxIoSampleResponse& rx, uintptr_t data);
117+
void printResponseCb(TxStatusResponse& status, uintptr_t data);
118+
void printResponseCb(Rx16Response& rx, uintptr_t data);
119+
void printResponseCb(Rx64Response& rx, uintptr_t data);
120+
void printResponseCb(Rx16IoSampleResponse& rx, uintptr_t data);
121+
void printResponseCb(Rx64IoSampleResponse& rx, uintptr_t data);
122+
void printResponseCb(ModemStatusResponse& status, uintptr_t data);
123+
void printResponseCb(AtCommandResponse& at, uintptr_t data);
124+
void printResponseCb(RemoteAtCommandResponse& at, uintptr_t data);
125+
void printResponseCb(XBeeResponse& r, uintptr_t data);
126+
88127
#endif // XBee_Printers_h

0 commit comments

Comments
 (0)