coap-example

Dependencies:   NetworkServices W5500Interface easy-connect

Fork of coap-example by Sergei G

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_coap_protocol.h"
00022 #include "sn_coap_header.h"
00023 
00024 UDPSocket socket;           // Socket to talk CoAP over
00025 Thread recvfromThread;      // Thread to receive messages over CoAP
00026 
00027 struct coap_s* coapHandle;
00028 coap_version_e coapVersion = COAP_VERSION_1;
00029 
00030 // CoAP HAL
00031 void* coap_malloc(uint16_t size) {
00032     return malloc(size);
00033 }
00034 
00035 void coap_free(void* addr) {
00036     free(addr);
00037 }
00038 
00039 // tx_cb and rx_cb are not used in this program
00040 uint8_t coap_tx_cb(uint8_t *a, uint16_t b, sn_nsdl_addr_s *c, void *d) {
00041     printf("coap tx cb\n");
00042     return 0;
00043 }
00044 
00045 int8_t coap_rx_cb(sn_coap_hdr_s *a, sn_nsdl_addr_s *b, void *c) {
00046     printf("coap rx cb\n");
00047     return 0;
00048 }
00049 
00050 // Main function for the recvfrom thread
00051 void recvfromMain() {
00052     SocketAddress addr;
00053     uint8_t* recv_buffer = (uint8_t*)malloc(1280); // Suggested is to keep packet size under 1280 bytes
00054 
00055     nsapi_size_or_error_t ret;
00056 
00057     while ((ret = socket.recvfrom(&addr, recv_buffer, 1280)) >= 0) {
00058         // to see where the message came from, inspect addr.get_addr() and addr.get_port()
00059 
00060         printf("Received a message of length '%d'\n", ret);
00061 
00062         sn_coap_hdr_s* parsed = sn_coap_parser(coapHandle, ret, recv_buffer, &coapVersion);
00063 
00064         // We know the payload is going to be a string
00065         std::string payload((const char*)parsed->payload_ptr, parsed->payload_len);
00066 
00067         printf("\tmsg_id:           %d\n", parsed->msg_id);
00068         printf("\tmsg_code:         %d\n", parsed->msg_code);
00069         printf("\tcontent_format:   %d\n", parsed->content_format);
00070         printf("\tpayload_len:      %d\n", parsed->payload_len);
00071         printf("\tpayload:          %s\n", payload.c_str());
00072         printf("\toptions_list_ptr: %p\n", parsed->options_list_ptr);
00073     }
00074 
00075     free(recv_buffer);
00076 
00077     printf("UDPSocket::recvfrom failed, error code %d. Shutting down receive thread.\n", ret);
00078 }
00079 
00080 int main() {
00081     printf("Easy connect...\n");
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 = "/test";
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("i-ce.itron.cloud", 5683, message_ptr, message_len);
00130     printf("Sent %d bytes to coap://i-ce.itron.cloud:5683\n", scount);
00131 
00132     free(coap_res_ptr);
00133     free(message_ptr);
00134 
00135     Thread::wait(osWaitForever);
00136 }