Skip to content

Commit 966b6d2

Browse files
committed
Added udp example and support for XBee 3 Cellular
Added more common methods
1 parent 32d9eaa commit 966b6d2

17 files changed

Lines changed: 553 additions & 90 deletions

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ This section provides an overview of the key methods available in the XBee class
5151
- `XBeeInit()`: Initializes the XBee module.
5252
- `XBeeConnect()`: Connects the XBee module to a network.
5353
- `XBeeDisconnect()`: Disconnects the XBee module from the network.
54-
- `XBeeSendData()`: Sends data through the XBee module.
54+
- `XBeeSendPacket()`: Sends data through the XBee module.
5555
- `XBeeSoftReset()`: Performs a soft reset on the XBee module.
5656
- `XBeeHardReset()`: Performs a hard reset on the XBee module.
5757
- `XBeeProcess()`: Processes incoming and outgoing data for the XBee module.
@@ -86,7 +86,7 @@ The following methods are specific to the XBee LR (LoRaWAN) subclass and are **n
8686
- `XBeeLRSetAppEUI()`: Configures the Application EUI used for OTAA join.
8787
- `XBeeLRSetAppKey()`: Sets the AppKey for LoRaWAN OTAA authentication.
8888
- `XBeeLRSetNwkKey()`: Sets the Network Key used for network traffic encryption.
89-
- `XBeeLRSendData()`: Sends a LoRaWAN uplink packet using the LR frame interface.
89+
- `XBeeLRSendPacket()`: Sends a LoRaWAN uplink packet using the LR frame interface.
9090

9191
Each of these methods provides essential functionality for managing and communicating with XBee devices within a network. Ensure that you refer to these methods when developing applications that involve XBee modules.
9292

@@ -170,7 +170,7 @@ After creating the XBee LR instance, initialize the XBee LR module, configure th
170170
171171
### Sending Data
172172
173-
To send data over the XBee LR network, use the `XBeeLRSendData` method. Here's an example of preparing and sending a payload:
173+
To send data over the XBee LR network, use the `XBeeLRSendPacket` method. Here's an example of preparing and sending a payload:
174174
175175
```c
176176
// XBeeLR payload to send
@@ -183,7 +183,7 @@ XBeeLRPacket_t packet = {
183183
.ack = 0,
184184
};
185185
186-
if (!XBeeSendData(myXbeeLr, &packet)) {
186+
if (!XBeeSendPacket(myXbeeLr, &packet)) {
187187
printf("Failed to send data.");
188188
} else {
189189
printf("Data sent successfully.");
@@ -307,7 +307,7 @@ int main() {
307307
.ack = 0,
308308
};
309309

310-
if (!XBeeSendData(myXbeeLr, &packet)) {
310+
if (!XBeeSendPacket(myXbeeLr, &packet)) {
311311
printf("Failed to send data.");
312312
} else {
313313
printf("Data sent successfully.");

examples/xbee_cellular/Makefile

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,22 @@ CORE_SRCS = $(SRC_DIR)/xbee.c \
2020
$(SRC_DIR)/xbee_at_cmds.c \
2121
$(SRC_DIR)/xbee_cellular.c
2222

23-
EXAMPLE_SRC = $(EXAMPLE_DIR)/xbee_cellular_http_get_example.c
24-
PORT_SRC = $(PORTS_DIR)/port_$(PLATFORM).c
23+
PORT_SRC = $(PORTS_DIR)/port_$(PLATFORM).c
2524

26-
OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, \
27-
$(notdir $(CORE_SRCS)) $(notdir $(EXAMPLE_SRC)) $(notdir $(PORT_SRC)))
25+
EXAMPLE_HTTP = $(EXAMPLE_DIR)/xbee_cellular_http_get_example.c
26+
EXAMPLE_UDP = $(EXAMPLE_DIR)/xbee_cellular_udp_echo_example.c
2827

29-
# Output binary
30-
TARGET = $(BUILD_DIR)/xbee_cellular_http_get_example
28+
OBJS_HTTP = $(patsubst %.c, $(BUILD_DIR)/%.o, \
29+
$(notdir $(CORE_SRCS)) $(notdir $(EXAMPLE_HTTP)) $(notdir $(PORT_SRC)))
30+
31+
OBJS_UDP = $(patsubst %.c, $(BUILD_DIR)/%.o, \
32+
$(notdir $(CORE_SRCS)) $(notdir $(EXAMPLE_UDP)) $(notdir $(PORT_SRC)))
33+
34+
TARGET_HTTP = $(BUILD_DIR)/xbee_cellular_http_get_example
35+
TARGET_UDP = $(BUILD_DIR)/xbee_cellular_udp_echo_example
3136

3237
# Default rule
33-
all: $(BUILD_DIR) $(TARGET)
38+
all: $(BUILD_DIR) $(TARGET_HTTP) $(TARGET_UDP)
3439

3540
# Create build directory
3641
$(BUILD_DIR):
@@ -47,7 +52,10 @@ $(BUILD_DIR)/%.o: $(PORTS_DIR)/%.c
4752
$(CC) $(CFLAGS) -c $< -o $@
4853

4954
# Linking
50-
$(TARGET): $(OBJS)
55+
$(TARGET_HTTP): $(OBJS_HTTP)
56+
$(CC) $(CFLAGS) $^ -o $@
57+
58+
$(TARGET_UDP): $(OBJS_UDP)
5159
$(CC) $(CFLAGS) $^ -o $@
5260

5361
clean:

examples/xbee_cellular/xbee_cellular_http_get_example.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/***************************************************************************//**
2-
* @file xbee_cellular_http_getexample.c
2+
* @file xbee_cellular_http_get_example.c
33
* @brief Example application demonstrating the use of the XBeeCellular driver.
44
*
55
* This file contains a sample application that demonstrates how to use the
@@ -56,19 +56,31 @@
5656
static bool responseReceived = false;
5757

5858
/**
59-
* Callback triggered when data is received via SOCKET_RECEIVE frame (0xCD).
59+
* @brief Callback triggered when data is received via SOCKET_RECEIVE (0xCD)
60+
* or SOCKET_RECEIVE_FROM (0xCE) frame.
6061
*
61-
* This function prints out the payload from the remote server in plain text format.
62-
* Typically used to handle HTTP response content received over TCP.
62+
* This function prints the payload from the remote peer in plain text format.
63+
* If the source IP and port are known (UDP), they are printed as well.
64+
*
65+
* @param[in] self Pointer to the XBee instance.
66+
* @param[in] data Pointer to the XBeeCellularPacket_t payload descriptor.
6367
*/
6468
void OnReceiveCallback(XBee* self, void* data) {
6569
(void)self;
6670
XBeeCellularPacket_t* packet = (XBeeCellularPacket_t*)data;
6771

6872
responseReceived = true;
6973

74+
if (packet->ip[0] != 0 || packet->remotePort != 0) {
75+
portDebugPrintf("Received from %u.%u.%u.%u:%u on socket %u\n",
76+
packet->ip[0], packet->ip[1], packet->ip[2], packet->ip[3],
77+
packet->remotePort, packet->socketId);
78+
} else {
79+
portDebugPrintf("Received on socket %u\n", packet->socketId);
80+
}
81+
7082
portDebugPrintf("[Payload ASCII Dump]:\n");
71-
for (int i = 0; i < packet->payloadSize; i++) {
83+
for (int i = 0; i < packet->payloadSize; ++i) {
7284
char c = packet->payload[i];
7385
portDebugPrintf("%c", (c >= 32 && c <= 126) ? c : '.');
7486
}
@@ -186,7 +198,7 @@ int main() {
186198
}
187199

188200
portDebugPrintf("HTTP transaction complete. Exiting.\n");
189-
XBeeCellularSocketClose((XBee*)xbee, socketId);
201+
XBeeCellularSocketClose((XBee*)xbee, socketId, false);
190202
XBeeCellularDestroy(xbee);
191203
return 0;
192204
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/***************************************************************************//**
2+
* @file xbee_cellular_udp_echo_example.c
3+
*
4+
* @brief Sends a UDP datagram to Digi’s public echo server (52.43.121.77:10001)
5+
* and prints the echoed payload when it comes back.
6+
*
7+
* The flow implements the Extended-Socket “UDP” example:
8+
* 1) Socket Create (0x40, protocol 0x02)
9+
* 2) Socket Bind (0x46, choose a local port)
10+
* 3) Socket SendTo (0x45) --> TX-Status (0x89)
11+
* 4) Socket ReceiveFrom (0xCE) --> our RX callback
12+
* 5) Socket Close (0x43) --> Close-Resp (0xCF)
13+
*
14+
* @author
15+
* Felix Galindo <felix.galindo@digi.com>
16+
* @license
17+
* MIT
18+
******************************************************************************/
19+
20+
#include "xbee_cellular.h"
21+
#include "port.h"
22+
#include <string.h>
23+
#include <stdio.h>
24+
#include <stdbool.h>
25+
26+
/* ---------- serial device per-platform ---------------------------------- */
27+
#if defined(_WIN32)
28+
#define DEFAULT_SERIAL_PORT "COM3"
29+
#elif defined(__APPLE__)
30+
#define DEFAULT_SERIAL_PORT "/dev/cu.usbserial-1110"
31+
#elif defined(__linux__)
32+
#define DEFAULT_SERIAL_PORT "/dev/ttyUSB0"
33+
#else
34+
#define DEFAULT_SERIAL_PORT ""
35+
#endif
36+
37+
/* ---------- globals ------------------------------------------------------ */
38+
static volatile bool echoReceived = false;
39+
40+
/* ---------- user callbacks ---------------------------------------------- */
41+
static void onReceive(XBee *self, void *frame)
42+
{
43+
(void)self;
44+
const XBeeCellularPacket_t *p = (const XBeeCellularPacket_t *)frame;
45+
46+
echoReceived = true;
47+
48+
portDebugPrintf("[UDP RX] %u bytes from %u.%u.%u.%u:%u (socket %u):\n",
49+
p->payloadSize,
50+
p->ip[0], p->ip[1], p->ip[2], p->ip[3],
51+
p->remotePort, p->socketId);
52+
53+
for (uint16_t i = 0; i < p->payloadSize; ++i) {
54+
char c = p->payload[i];
55+
portDebugPrintf("%c", (c >= 32 && c <= 126) ? c : '.');
56+
}
57+
portDebugPrintf("\n");
58+
}
59+
60+
static void onSend(XBee *self, void *frame)
61+
{
62+
(void)self;
63+
(void)frame;
64+
portDebugPrintf("[UDP TX] payload accepted for transmit\n");
65+
}
66+
67+
/* ---------- main --------------------------------------------------------- */
68+
int main(void)
69+
{
70+
/* Hardware abstraction table ------------------------------------------- */
71+
const XBeeHTable hw = {
72+
.PortUartInit = portUartInit,
73+
.PortUartRead = portUartRead,
74+
.PortUartWrite = portUartWrite,
75+
.PortFlushRx = portFlushRx,
76+
.PortDelay = portDelay,
77+
.PortMillis = portMillis
78+
};
79+
80+
/* Callback table ------------------------------------------------------- */
81+
const XBeeCTable cb = {
82+
.OnReceiveCallback = onReceive,
83+
.OnSendCallback = onSend
84+
};
85+
86+
portDebugPrintf("XBee 3 Cellular – UDP Echo example (Extended Socket)\n");
87+
88+
/* Instance ------------------------------------------------------------- */
89+
XBeeCellular *xbee = XBeeCellularCreate(&cb, &hw);
90+
91+
if (!XBeeInit((XBee *)xbee, 9600, DEFAULT_SERIAL_PORT)) {
92+
portDebugPrintf("[ERR] failed to open serial port\n");
93+
return -1;
94+
}
95+
96+
/* APN etc. – identical to the HTTP example ---------------------------- */
97+
const XBeeCellularConfig_t cfg = {
98+
.apn = "broadband",
99+
.simPin = "",
100+
.carrier = ""
101+
};
102+
XBeeConfigure((XBee *)xbee, &cfg);
103+
104+
/* Attach to network ---------------------------------------------------- */
105+
portDebugPrintf("Waiting for network attach...\n");
106+
XBeeConnect((XBee *)xbee, false);
107+
while (!XBeeCellularConnected((XBee *)xbee)) {
108+
portDelay(1000);
109+
portDebugPrintf(".");
110+
}
111+
portDebugPrintf("\n[OK] attached!\n");
112+
113+
/* 1) Socket Create (protocol = UDP 0x02) ------------------------------- */
114+
uint8_t sockId = 0;
115+
if (!XBeeCellularSocketCreate((XBee *)xbee, XBEE_PROTOCOL_UDP, &sockId)) {
116+
portDebugPrintf("[ERR] socket create failed\n");
117+
return -1;
118+
}
119+
120+
/* 2) Bind to local port 0x1234 ---------------------------------------- */
121+
if (!XBeeCellularSocketBind((XBee *)xbee, sockId, 0x1234, true)) {
122+
portDebugPrintf("[ERR] bind failed\n");
123+
return -1;
124+
}
125+
portDebugPrintf("[OK] socket %u bound to local port 0x1234\n", sockId);
126+
127+
/* 3) SendTo Digi echo server ------------------------------------------ */
128+
const uint8_t ip[4] = { 52, 43, 121, 77 };
129+
const uint8_t payload[] = "echo this";
130+
131+
if (!XBeeCellularSocketSendTo((XBee *)xbee,
132+
sockId,
133+
ip,
134+
10001,
135+
payload,
136+
sizeof(payload) - 1))
137+
{
138+
portDebugPrintf("[ERR] sendto failed\n");
139+
return -1;
140+
}
141+
portDebugPrintf("[OK] UDP datagram sent, waiting for echo...\n");
142+
143+
/* 4) Wait (≤10 s) for echo --------------------------------------------- */
144+
uint32_t t0 = portMillis();
145+
while (!echoReceived && (portMillis() - t0) < 10000) {
146+
XBeeProcess((XBee *)xbee);
147+
portDelay(100);
148+
}
149+
150+
if (!echoReceived)
151+
portDebugPrintf("[WARN] timed-out waiting for echo\n");
152+
153+
/* 5) Close socket ------------------------------------------------------ */
154+
XBeeCellularSocketClose((XBee *)xbee, sockId, false);
155+
156+
XBeeCellularDestroy(xbee);
157+
portDebugPrintf("Done.\n");
158+
return 0;
159+
}

examples/xbee_lr/xbee_lr_example.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ int main() {
168168
portDebugPrintf("%02X", examplePayload[i]);
169169
}
170170
portDebugPrintf("\n");
171-
if (XBeeSendData((XBee*)myXbeeLr, &packet)) {
171+
if (XBeeSendPacket((XBee*)myXbeeLr, &packet)) {
172172
printf("Failed to send data.\n");
173173
} else {
174174
printf("Data sent successfully.\n");

include/xbee.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ struct XBee {
134134
bool XBeeInit(XBee* self, uint32_t baudrate, void* device);
135135
bool XBeeConnect(XBee* self, bool blocking);
136136
bool XBeeDisconnect(XBee* self);
137-
uint8_t XBeeSendData(XBee* self, const void*);
137+
uint8_t XBeeSendPacket(XBee* self, const void*);
138138
bool XBeeSoftReset(XBee* self);
139139
void XBeeHardReset(XBee* self);
140140
void XBeeProcess(XBee* self);
@@ -144,6 +144,13 @@ bool XBeeApplyChanges(XBee* self);
144144
bool XBeeSetAPIOptions(XBee* self, const uint8_t value);
145145
bool XBeeGetFirmwareVersion(XBee* self, uint32_t* version);
146146
bool XBeeConfigure(XBee* self, const void* config);
147+
bool XBeeFactoryReset (XBee* self); /* ATFR */
148+
bool XBeeExitCommandMode (XBee* self); /* ATCN */
149+
bool XBeeSetApiEnable (XBee* self, uint8_t mode); /* ATAP */
150+
bool XBeeSetBaudRate (XBee* self, uint8_t rateCode); /* ATBD */
151+
bool XBeeGetLastRssi (XBee* self, int8_t* rssiOut); /* ATDB */
152+
bool XBeeGetHardwareVersion (XBee* self, uint16_t* hvOut); /* ATHV */
153+
bool XBeeGetSerialNumber (XBee* self, uint64_t* snOut); /* ATSH/ATSL */
147154

148155
#if defined(__cplusplus)
149156
}

include/xbee_api_frames.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,17 @@
232232
XBEE_API_TYPE_CELLULAR_SOCKET_CONNECT = 0x42, ///< Frame to connect a socket
233233
XBEE_API_TYPE_CELLULAR_SOCKET_CLOSE = 0x43, ///< Frame to close a socket
234234
XBEE_API_TYPE_CELLULAR_SOCKET_SEND = 0x44, ///< Frame to send socket data
235+
XBEE_API_TYPE_CELLULAR_SOCKET_SEND_TO = 0x45, ///< Frame to send UDP data to a specific address
236+
XBEE_API_TYPE_CELLULAR_SOCKET_BIND = 0x46, ///< Frame to bind a socket to a local port
235237
XBEE_API_TYPE_CELLULAR_SOCKET_CREATE_RESPONSE = 0xC0, ///< Response to socket create
236238
XBEE_API_TYPE_CELLULAR_SOCKET_OPTION_RESPONSE = 0xC1, ///< Response to socket option
237239
XBEE_API_TYPE_CELLULAR_SOCKET_CONNECT_RESPONSE = 0xC2, ///< Response to socket connect
240+
XBEE_API_TYPE_CELLULAR_SOCKET_CLOSE_RESPONSE = 0xC3, ///< Response to socket close
241+
XBEE_API_TYPE_CELLULAR_SOCKET_BIND_RESPONSE = 0xC6, ///< Response to socket bind
242+
238243
XBEE_API_TYPE_CELLULAR_SOCKET_RX = 0xCD, ///< Frame for receiving data
239244
XBEE_API_TYPE_CELLULAR_SOCKET_RX_FROM = 0xCE, ///< Frame for receiving UDP data with source
240-
XBEE_API_TYPE_CELLULAR_SOCKET_STATUS = 0xCF, ///< Frame for socket status
245+
XBEE_API_TYPE_CELLULAR_SOCKET_STATUS = 0xCF, ///< Frame for socket status
241246

242247
/**< XBee GPIO/ADC Related API Frames */
243248
XBEE_API_TYPE_IO_DATA_SAMPLE_RX = 0x92, ///< Frame for receiving IO data samples (GPIO/ADC)

include/xbee_at_cmds.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ typedef enum {
6060
AT_AP, /**< API Enable */
6161
AT_BD, /**< Baud Rate */
6262
AT_WR, /**< Write to non-volatile memory */
63-
AT_RE, /**< Restore factory defaults */
63+
AT_RE, /**< Soft Reset */
64+
AT_FR, /**< Factory Reset */
6465
AT_VR, /**< Firmware Version */
6566
AT_AC, /**< Apply Changes */
6667
AT_NR, /**< Network Reset */
@@ -114,7 +115,7 @@ typedef enum {
114115
AT_JV, /**< Channel Verification */
115116
AT_LD, /**< Node Discovery Time */
116117
AT_AO, /**< API Options */
117-
118+
AT_HV, /**< Hardware Version */
118119
//@todo: move xbee familiar specific commands to their own file
119120

120121
/**< XBee 3 RF Specific AT Commands */

0 commit comments

Comments
 (0)