CoAP example application for mbed OS 5

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * PackageLicenseDeclared: Apache-2.0
00003  * Copyright (c) 2017 ARM Limited
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include <string>
00019 #include "mbed.h"
00020 #include "easy-connect.h"
00021 #include "sn_nsdl.h"
00022 #include "sn_coap_protocol.h"
00023 #include "sn_coap_header.h"
00024 
00025 UDPSocket socket;           // Socket to talk CoAP over
00026 Thread recvfromThread;      // Thread to receive messages over CoAP
00027 
00028 struct coap_s* coapHandle;
00029 coap_version_e coapVersion = COAP_VERSION_1;
00030 
00031 // CoAP HAL
00032 void* coap_malloc(uint16_t size) {
00033     return malloc(size);
00034 }
00035 
00036 void coap_free(void* addr) {
00037     free(addr);
00038 }
00039 
00040 // tx_cb and rx_cb are not used in this program
00041 uint8_t coap_tx_cb(uint8_t *a, uint16_t b, sn_nsdl_addr_s *c, void *d) {
00042     printf("coap tx cb\n");
00043     return 0;
00044 }
00045 
00046 int8_t coap_rx_cb(sn_coap_hdr_s *a, sn_nsdl_addr_s *b, void *c) {
00047     printf("coap rx cb\n");
00048     return 0;
00049 }
00050 
00051 // Main function for the recvfrom thread
00052 void recvfromMain() {
00053     SocketAddress addr;
00054     uint8_t* recv_buffer = (uint8_t*)malloc(1280); // Suggested is to keep packet size under 1280 bytes
00055 
00056     nsapi_size_or_error_t ret;
00057 
00058     while ((ret = socket.recvfrom(&addr, recv_buffer, 1280)) >= 0) {
00059         // to see where the message came from, inspect addr.get_addr() and addr.get_port()
00060 
00061         printf("Received a message of length '%d'\n", ret);
00062 
00063         sn_coap_hdr_s* parsed = sn_coap_parser(coapHandle, ret, recv_buffer, &coapVersion);
00064 
00065         // We know the payload is going to be a string
00066         std::string payload((const char*)parsed->payload_ptr, parsed->payload_len);
00067 
00068         printf("\tmsg_id:           %d\n", parsed->msg_id);
00069         printf("\tmsg_code:         %d\n", parsed->msg_code);
00070         printf("\tcontent_format:   %d\n", parsed->content_format);
00071         printf("\tpayload_len:      %d\n", parsed->payload_len);
00072         printf("\tpayload:          %s\n", payload.c_str());
00073         printf("\toptions_list_ptr: %p\n", parsed->options_list_ptr);
00074     }
00075 
00076     free(recv_buffer);
00077 
00078     printf("UDPSocket::recvfrom failed, error code %d. Shutting down receive thread.\n", ret);
00079 }
00080 
00081 int main() {
00082     NetworkInterface *network = easy_connect(true);
00083     if (!network) {
00084         printf("Cannot connect to the network, see serial output");
00085         return 1;
00086     }
00087 
00088     printf("Connected to the network. Opening a socket...\n");
00089 
00090     // Open a socket on the network interface
00091     socket.open(network);
00092 
00093     // Initialize the CoAP protocol handle, pointing to local implementations on malloc/free/tx/rx functions
00094     coapHandle = sn_coap_protocol_init(&coap_malloc, &coap_free, &coap_tx_cb, &coap_rx_cb);
00095 
00096     // UDPSocket::recvfrom is blocking, so run it in a separate RTOS thread
00097     recvfromThread.start(&recvfromMain);
00098 
00099     // Path to the resource we want to retrieve
00100     const char* coap_uri_path = "/hello";
00101 
00102     // See ns_coap_header.h
00103     sn_coap_hdr_s *coap_res_ptr = (sn_coap_hdr_s*)calloc(sizeof(sn_coap_hdr_s), 1);
00104     coap_res_ptr->uri_path_ptr = (uint8_t*)coap_uri_path;       // Path
00105     coap_res_ptr->uri_path_len = strlen(coap_uri_path);
00106     coap_res_ptr->msg_code = COAP_MSG_CODE_REQUEST_GET;         // CoAP method
00107     coap_res_ptr->content_format = COAP_CT_TEXT_PLAIN;          // CoAP content type
00108     coap_res_ptr->payload_len = 0;                              // Body length
00109     coap_res_ptr->payload_ptr = 0;                              // Body pointer
00110     coap_res_ptr->options_list_ptr = 0;                         // Optional: options list
00111     // Message ID is used to track request->response patterns, because we're using UDP (so everything is unconfirmed).
00112     // See the receive code to verify that we get the same message ID back
00113     coap_res_ptr->msg_id = 7;
00114 
00115     // Calculate the CoAP message size, allocate the memory and build the message
00116     uint16_t message_len = sn_coap_builder_calc_needed_packet_data_size(coap_res_ptr);
00117     printf("Calculated message length: %d bytes\n", message_len);
00118 
00119     uint8_t* message_ptr = (uint8_t*)malloc(message_len);
00120     sn_coap_builder(message_ptr, coap_res_ptr);
00121 
00122     // Uncomment to see the raw buffer that will be sent...
00123     // printf("Message is: ");
00124     // for (size_t ix = 0; ix < message_len; ix++) {
00125     //     printf("%02x ", message_ptr[ix]);
00126     // }
00127     // printf("\n");
00128 
00129     int scount = socket.sendto("coap.me", 5683, message_ptr, message_len);
00130     printf("Sent %d bytes to coap://coap.me:5683\n", scount);
00131 
00132     free(coap_res_ptr);
00133     free(message_ptr);
00134 
00135     Thread::wait(osWaitForever);
00136 }