Skip to content

Commit 782be82

Browse files
mprseAmanda ButlerQinghao Shi
authored
Add cellular example app example (#103)
* Add Cellular app example * Add cellular config to test.json * Cellular example: add missing header * Edit README.md Edit file, mostly for consistent capitalization across docs. Co-authored-by: Amanda Butler <[email protected]> Co-authored-by: Qinghao Shi <[email protected]>
1 parent 58bd9c9 commit 782be82

File tree

4 files changed

+346
-1
lines changed

4 files changed

+346
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
## Cellular application example
2+
3+
This example is based on Mbed OS cellular APIs and demonstrates a TCP or UDP echo transaction with a public echo server.
4+
5+
**Note:** Provide network and SIM credentials in the `mbed_app.json` configuration file.
Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
/*
2+
* Copyright (c) 2006-2020 Arm Limited and affiliates.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
#include "mbed.h"
6+
#include "common_functions.h"
7+
#include "CellularNonIPSocket.h"
8+
#include "CellularDevice.h"
9+
#include "UDPSocket.h"
10+
#include "CellularLog.h"
11+
12+
#define UDP 0
13+
#define TCP 1
14+
#define NONIP 2
15+
16+
// Number of retries /
17+
#define RETRY_COUNT 3
18+
19+
NetworkInterface *iface;
20+
21+
// Echo server hostname
22+
const char *host_name = MBED_CONF_APP_ECHO_SERVER_HOSTNAME;
23+
24+
// Echo server port (same for TCP and UDP)
25+
const int port = MBED_CONF_APP_ECHO_SERVER_PORT;
26+
27+
static rtos::Mutex trace_mutex;
28+
29+
#if MBED_CONF_MBED_TRACE_ENABLE
30+
static void trace_wait()
31+
{
32+
trace_mutex.lock();
33+
}
34+
35+
static void trace_release()
36+
{
37+
trace_mutex.unlock();
38+
}
39+
40+
static char time_st[50];
41+
42+
static char *trace_time(size_t ss)
43+
{
44+
snprintf(time_st, 49, "[%08llums]", Kernel::get_ms_count());
45+
return time_st;
46+
}
47+
48+
static void trace_open()
49+
{
50+
mbed_trace_init();
51+
mbed_trace_prefix_function_set(&trace_time);
52+
53+
mbed_trace_mutex_wait_function_set(trace_wait);
54+
mbed_trace_mutex_release_function_set(trace_release);
55+
56+
mbed_cellular_trace::mutex_wait_function_set(trace_wait);
57+
mbed_cellular_trace::mutex_release_function_set(trace_release);
58+
}
59+
60+
static void trace_close()
61+
{
62+
mbed_cellular_trace::mutex_wait_function_set(NULL);
63+
mbed_cellular_trace::mutex_release_function_set(NULL);
64+
65+
mbed_trace_free();
66+
}
67+
#endif // #if MBED_CONF_MBED_TRACE_ENABLE
68+
69+
Thread dot_thread(osPriorityNormal, 512);
70+
71+
void print_function(const char *format, ...)
72+
{
73+
trace_mutex.lock();
74+
va_list arglist;
75+
va_start(arglist, format);
76+
vprintf(format, arglist);
77+
va_end(arglist);
78+
trace_mutex.unlock();
79+
}
80+
81+
void dot_event()
82+
{
83+
while (true) {
84+
ThisThread::sleep_for(4000);
85+
if (iface && iface->get_connection_status() == NSAPI_STATUS_GLOBAL_UP) {
86+
break;
87+
} else {
88+
trace_mutex.lock();
89+
printf(".");
90+
fflush(stdout);
91+
trace_mutex.unlock();
92+
}
93+
}
94+
}
95+
96+
/**
97+
* Connects to the Cellular Network
98+
*/
99+
nsapi_error_t do_connect()
100+
{
101+
nsapi_error_t retcode = NSAPI_ERROR_OK;
102+
uint8_t retry_counter = 0;
103+
104+
while (iface->get_connection_status() != NSAPI_STATUS_GLOBAL_UP) {
105+
retcode = iface->connect();
106+
if (retcode == NSAPI_ERROR_AUTH_FAILURE) {
107+
print_function("\n\nAuthentication Failure. Exiting application\n");
108+
} else if (retcode == NSAPI_ERROR_OK) {
109+
print_function("\n\nConnection Established.\n");
110+
} else if (retry_counter > RETRY_COUNT) {
111+
print_function("\n\nFatal connection failure: %d\n", retcode);
112+
} else {
113+
print_function("\n\nCouldn't connect: %d, will retry\n", retcode);
114+
retry_counter++;
115+
continue;
116+
}
117+
break;
118+
}
119+
return retcode;
120+
}
121+
122+
/**
123+
* Opens:
124+
* - UDP or TCP socket with the given echo server and performs an echo
125+
* transaction retrieving current.
126+
* - Cellular Non-IP socket for which the data delivery path is decided
127+
* by network's control plane CIoT optimisation setup, for the given APN.
128+
*/
129+
nsapi_error_t test_send_recv()
130+
{
131+
nsapi_size_or_error_t retcode;
132+
#if MBED_CONF_APP_SOCK_TYPE == TCP
133+
TCPSocket sock;
134+
#elif MBED_CONF_APP_SOCK_TYPE == UDP
135+
UDPSocket sock;
136+
#elif MBED_CONF_APP_SOCK_TYPE == NONIP
137+
CellularNonIPSocket sock;
138+
#endif
139+
140+
#if MBED_CONF_APP_SOCK_TYPE == NONIP
141+
retcode = sock.open((CellularContext *)iface);
142+
#else
143+
retcode = sock.open(iface);
144+
#endif
145+
146+
if (retcode != NSAPI_ERROR_OK) {
147+
#if MBED_CONF_APP_SOCK_TYPE == TCP
148+
print_function("TCPSocket.open() fails, code: %d\n", retcode);
149+
#elif MBED_CONF_APP_SOCK_TYPE == UDP
150+
print_function("UDPSocket.open() fails, code: %d\n", retcode);
151+
#elif MBED_CONF_APP_SOCK_TYPE == NONIP
152+
print_function("CellularNonIPSocket.open() fails, code: %d\n", retcode);
153+
#endif
154+
return -1;
155+
}
156+
157+
int n = 0;
158+
const char *echo_string = "TEST";
159+
char recv_buf[4];
160+
161+
sock.set_timeout(15000);
162+
163+
#if MBED_CONF_APP_SOCK_TYPE == NONIP
164+
retcode = sock.send((void *) echo_string, strlen(echo_string));
165+
if (retcode < 0) {
166+
print_function("CellularNonIPSocket.send() fails, code: %d\n", retcode);
167+
return -1;
168+
} else {
169+
print_function("CellularNonIPSocket: Sent %d Bytes\n", retcode);
170+
}
171+
172+
n = sock.recv((void *) recv_buf, sizeof(recv_buf));
173+
174+
#else
175+
176+
SocketAddress sock_addr;
177+
retcode = iface->gethostbyname(host_name, &sock_addr);
178+
if (retcode != NSAPI_ERROR_OK) {
179+
print_function("Couldn't resolve remote host: %s, code: %d\n", host_name, retcode);
180+
return -1;
181+
}
182+
183+
sock_addr.set_port(port);
184+
185+
#if MBED_CONF_APP_SOCK_TYPE == TCP
186+
retcode = sock.connect(sock_addr);
187+
if (retcode < 0) {
188+
print_function("TCPSocket.connect() fails, code: %d\n", retcode);
189+
return -1;
190+
} else {
191+
print_function("TCP: connected with %s server\n", host_name);
192+
}
193+
retcode = sock.send((void *) echo_string, strlen(echo_string));
194+
if (retcode < 0) {
195+
print_function("TCPSocket.send() fails, code: %d\n", retcode);
196+
return -1;
197+
} else {
198+
print_function("TCP: Sent %d Bytes to %s\n", retcode, host_name);
199+
}
200+
201+
n = sock.recv((void *) recv_buf, sizeof(recv_buf));
202+
#else
203+
204+
retcode = sock.sendto(sock_addr, (void *) echo_string, strlen(echo_string));
205+
if (retcode < 0) {
206+
print_function("UDPSocket.sendto() fails, code: %d\n", retcode);
207+
return -1;
208+
} else {
209+
print_function("UDP: Sent %d Bytes to %s\n", retcode, host_name);
210+
}
211+
212+
n = sock.recvfrom(&sock_addr, (void *) recv_buf, sizeof(recv_buf));
213+
#endif
214+
#endif
215+
216+
sock.close();
217+
218+
if (n > 0) {
219+
print_function("Received from echo server %d Bytes\n", n);
220+
return 0;
221+
}
222+
223+
return -1;
224+
}
225+
226+
int main()
227+
{
228+
print_function("\n\nmbed-os-example-cellular\n");
229+
print_function("\n\nBuilt: %s, %s\n", __DATE__, __TIME__);
230+
#ifdef MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN
231+
print_function("\n\n[MAIN], plmn: %s\n", (MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN ? MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN : "NULL"));
232+
#endif
233+
234+
print_function("Establishing connection\n");
235+
#if MBED_CONF_MBED_TRACE_ENABLE
236+
trace_open();
237+
#else
238+
dot_thread.start(dot_event);
239+
#endif // #if MBED_CONF_MBED_TRACE_ENABLE
240+
241+
#if MBED_CONF_APP_SOCK_TYPE == NONIP
242+
iface = CellularContext::get_default_nonip_instance();
243+
#else
244+
iface = CellularContext::get_default_instance();
245+
#endif
246+
247+
MBED_ASSERT(iface);
248+
249+
// sim pin, apn, credentials and possible plmn are taken automatically from json when using NetworkInterface::set_default_parameters()
250+
iface->set_default_parameters();
251+
252+
nsapi_error_t retcode = NSAPI_ERROR_NO_CONNECTION;
253+
254+
/* Attempt to connect to a cellular network */
255+
if (do_connect() == NSAPI_ERROR_OK) {
256+
retcode = test_send_recv();
257+
}
258+
259+
if (iface->disconnect() != NSAPI_ERROR_OK) {
260+
print_function("\n\n disconnect failed.\n\n");
261+
}
262+
263+
if (retcode == NSAPI_ERROR_OK) {
264+
print_function("\n\nSuccess. Exiting \n\n");
265+
} else {
266+
print_function("\n\nFailure. Exiting \n\n");
267+
}
268+
269+
#if MBED_CONF_MBED_TRACE_ENABLE
270+
trace_close();
271+
#else
272+
dot_thread.terminate();
273+
#endif // #if MBED_CONF_MBED_TRACE_ENABLE
274+
275+
return 0;
276+
}
277+
// EOF
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"config": {
3+
"sock-type": "TCP",
4+
"echo-server-hostname": {
5+
"help": "Echo server host name.",
6+
"value": "\"echo.mbedcloudtesting.com\""
7+
},
8+
"echo-server-port": {
9+
"help": "Echo server port number.",
10+
"value": 7
11+
},
12+
"trace-level": {
13+
"help": "Options are TRACE_LEVEL_ERROR,TRACE_LEVEL_WARN,TRACE_LEVEL_INFO,TRACE_LEVEL_DEBUG",
14+
"macro_name": "MBED_TRACE_MAX_LEVEL",
15+
"value": "TRACE_LEVEL_INFO"
16+
}
17+
},
18+
"target_overrides": {
19+
"*": {
20+
"target.network-default-interface-type": "CELLULAR",
21+
"mbed-trace.enable": false,
22+
"lwip.ipv4-enabled": true,
23+
"ppp.ipv4-enabled": true,
24+
"lwip.ipv6-enabled": true,
25+
"ppp.ipv6-enabled": true,
26+
"lwip.ethernet-enabled": false,
27+
"lwip.ppp-enabled": true,
28+
"lwip.tcp-enabled": true,
29+
"platform.stdio-convert-newlines": true,
30+
"platform.stdio-baud-rate": 115200,
31+
"platform.default-serial-baud-rate": 115200,
32+
"platform.stdio-buffered-serial": true,
33+
"cellular.debug-at": false,
34+
"cellular.use-apn-lookup": true,
35+
"nsapi.default-cellular-sim-pin": null,
36+
"nsapi.default-cellular-plmn": null,
37+
"nsapi.default-cellular-apn": null,
38+
"nsapi.default-cellular-username": null,
39+
"nsapi.default-cellular-password": null
40+
},
41+
"DISCO_L496AG": {
42+
"target.macros_add": [
43+
"CELLULAR_DEVICE=STModCellular"
44+
],
45+
"target.components_add": ["STMOD_CELLULAR"],
46+
"stmod_cellular.provide-default": "true"
47+
}
48+
}
49+
}

test.json

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,21 @@
1111
"wifi-password": {
1212
"help": "WiFi Password",
1313
"value": "\"Password\""
14-
}
14+
},
15+
"sock-type": "TCP",
16+
"echo-server-hostname": {
17+
"help": "Echo server host name.",
18+
"value": "\"echo.mbedcloudtesting.com\""
19+
},
20+
"echo-server-port": {
21+
"help": "Echo server port number.",
22+
"value": 7
23+
},
24+
"trace-level": {
25+
"help": "Options are TRACE_LEVEL_ERROR,TRACE_LEVEL_WARN,TRACE_LEVEL_INFO,TRACE_LEVEL_DEBUG",
26+
"macro_name": "MBED_TRACE_MAX_LEVEL",
27+
"value": "TRACE_LEVEL_INFO"
28+
}
1529
},
1630
"target_overrides": {
1731
"K64F":{

0 commit comments

Comments
 (0)