Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MAX44000 PWM_Tone_Library nexpaq_mdk
Fork of LED_Demo by
mbed_client.c
00001 /* 00002 * Copyright (c) 2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include <arpa/inet.h> 00018 #include <netinet/in.h> 00019 #include <stdio.h> 00020 #include <stdlib.h> 00021 #include <string.h> 00022 #include <sys/socket.h> 00023 #include <signal.h> /* For SIGIGN and SIGINT */ 00024 #include <unistd.h> 00025 #include <errno.h> 00026 #include <pthread.h> 00027 #include "sn_nsdl.h" 00028 #include "sn_coap_header.h" 00029 #include "sn_coap_protocol.h" 00030 #include "sn_nsdl_lib.h" 00031 #include "ns_list.h" 00032 #include "sn_grs.h" 00033 #include "arguments.h" 00034 #include "resource_generation_help.h" 00035 00036 #define BUFLEN 1024 00037 00038 /* Resource paths and values */ 00039 static uint8_t res_manufacturer[] = {"3/0/0"}; 00040 static uint8_t res_manufacturer_val[] = {"ARM"}; 00041 static uint8_t res_model_number[] = {"3/0/1"}; 00042 static uint8_t res_model_number_val[] = {"1.00"}; 00043 00044 static uint8_t res_temp[] = {"3303/0/temp"}; 00045 static uint8_t res_type_test[] = {"t"}; 00046 00047 struct thread_data_struct { 00048 struct nsdl_s *handle; 00049 struct sockaddr_in sa_dst; 00050 struct sockaddr_in sa_src; 00051 int sock_server; 00052 socklen_t slen_sa_dst; 00053 int thread_id; 00054 sn_nsdl_ep_parameters_s *endpoint_ptr; 00055 sn_nsdl_addr_s received_packet_address; 00056 ns_list_link_t link; 00057 bool registered; 00058 uint32_t ns_system_time; 00059 uint8_t delayed_token[8]; 00060 uint8_t delayed_token_len; 00061 sn_coap_msg_type_e delayed_msg_type; 00062 uint8_t delayed_response_cnt; 00063 uint8_t res_temp_val[16]; 00064 }; 00065 typedef struct thread_data_struct thread_data_struct_s; 00066 00067 extern void stop_pgm(); 00068 extern void *own_alloc(uint16_t size); 00069 extern void own_free(void* ptr); 00070 00071 /* Function templates */ 00072 int register_endpoint(int port, sn_nsdl_ep_parameters_s *endpoint, int thread_id); 00073 uint8_t tx_function(struct nsdl_s *handle, sn_nsdl_capab_e protocol , uint8_t *data, uint16_t len, sn_nsdl_addr_s *address); 00074 uint8_t rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_header, sn_nsdl_addr_s *address); 00075 static void ctrl_c_handle_function(); 00076 typedef void (*signalhandler_t)(int); 00077 void coap_exec_poll_function(int thread_id); 00078 int16_t receive_msg(thread_data_struct_s *data_item, uint8_t *buf); 00079 uint8_t general_resource_cb(struct nsdl_s *handle, sn_coap_hdr_s *coap_ptr, sn_nsdl_addr_s *address, sn_nsdl_capab_e protocol); 00080 int8_t compare_uripaths(sn_coap_hdr_s *coap_header, const uint8_t *uri_path_to_compare); 00081 void send_ack(struct nsdl_s *handle, sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address); 00082 00083 /* CoAP related globals*/ 00084 uint8_t text_plain = COAP_CT_TEXT_PLAIN; 00085 uint8_t link_format = COAP_CT_LINK_FORMAT; 00086 00087 /* Resource related globals*/ 00088 uint8_t *reg_location = 0; 00089 int8_t reg_location_len; 00090 00091 /* List containing thread specific data */ 00092 typedef NS_LIST_HEAD(thread_data_struct_s, link) thread_data_struct_t; 00093 static thread_data_struct_t NS_LIST_NAME_INIT(data_list); 00094 00095 /*****************************************************/ 00096 /* This is called from main to start the CoAP server */ 00097 /*****************************************************/ 00098 int register_endpoint(int port, sn_nsdl_ep_parameters_s *endpoint, int thread_id) 00099 { 00100 printf("Register endpoint, port: %d, thread id: %d\n", port, thread_id); 00101 thread_data_struct_s *data_item = NULL; 00102 uint8_t nsp_addr[16]; 00103 pthread_t coap_exec_thread; 00104 uint8_t received_address[4]; 00105 uint8_t buf[BUFLEN]; 00106 int16_t rcv_size=0; 00107 00108 data_item = malloc(sizeof(thread_data_struct_s)); 00109 data_item->slen_sa_dst = sizeof(data_item->sa_dst); 00110 memset(&data_item->received_packet_address, 0, sizeof(sn_nsdl_addr_s)); 00111 memset(&data_item->sa_dst, 0, sizeof(struct sockaddr_in)); 00112 memset(&data_item->sa_src, 0, sizeof(struct sockaddr_in)); 00113 data_item->received_packet_address.addr_ptr = received_address; 00114 data_item->endpoint_ptr = endpoint; 00115 data_item->registered = false; 00116 data_item->thread_id = thread_id; 00117 data_item->ns_system_time = 1; 00118 data_item->delayed_token_len = 0; 00119 data_item->delayed_response_cnt = 0; 00120 00121 /* Initial values for temperature */ 00122 char temp[10]; 00123 if (thread_id >= 9) { 00124 sprintf(temp, "25.%d", thread_id); 00125 } else { 00126 sprintf(temp, "2%d.0", thread_id); 00127 } 00128 strcpy(data_item->res_temp_val,temp); 00129 00130 sn_nsdl_resource_info_s *resource_ptr = 0; 00131 00132 if (signal(SIGINT, (signalhandler_t)ctrl_c_handle_function) == SIG_ERR) { 00133 printf("Error with SIGINT: %s\n", strerror(errno)); 00134 return -1; 00135 } 00136 00137 /* Open the server socket*/ 00138 if ((data_item->sock_server=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) ==-1 ) { 00139 stop_pgm("socket() error"); 00140 } 00141 00142 /* Init the listen port addr*/ 00143 memset((char *) &data_item->sa_src, 0, sizeof(data_item->sa_src)); 00144 data_item->sa_src.sin_family = AF_INET; 00145 data_item->sa_src.sin_port = htons(port); 00146 00147 /* Listen to the port */ 00148 data_item->sa_src.sin_addr.s_addr = INADDR_ANY; 00149 if (bind(data_item->sock_server, (struct sockaddr *) &data_item->sa_src, sizeof(data_item->sa_src) ) == -1) { 00150 stop_pgm("bind() error"); 00151 } 00152 00153 data_item->handle = sn_nsdl_init(&tx_function, &rx_function, &own_alloc, &own_free); 00154 inet_pton(AF_INET, arg_dst, &nsp_addr); 00155 00156 set_NSP_address(data_item->handle, nsp_addr, arg_dport, SN_NSDL_ADDRESS_TYPE_IPV4); 00157 ns_list_add_to_start(&data_list, data_item); 00158 00159 pthread_create(&coap_exec_thread, NULL, (void *)coap_exec_poll_function, data_item->thread_id); 00160 00161 resource_ptr = own_alloc(sizeof(sn_nsdl_resource_info_s)); 00162 if(!resource_ptr) { 00163 return 0; 00164 } 00165 00166 memset(resource_ptr, 0, sizeof(sn_nsdl_resource_info_s)); 00167 resource_ptr->resource_parameters_ptr = own_alloc(sizeof(sn_nsdl_resource_parameters_s)); 00168 if(!resource_ptr->resource_parameters_ptr) { 00169 own_free(resource_ptr); 00170 return 0; 00171 } 00172 memset(resource_ptr->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); 00173 00174 /* Create resources */ 00175 CREATE_STATIC_RESOURCE(resource_ptr, sizeof(res_manufacturer)-1, (uint8_t*) res_manufacturer, sizeof(res_type_test)-1, 00176 (uint8_t*)res_type_test, (uint8_t*) res_manufacturer_val, 00177 sizeof(res_manufacturer_val)-1, data_item->handle); 00178 00179 CREATE_STATIC_RESOURCE(resource_ptr, sizeof(res_model_number)-1, (uint8_t*) res_model_number, sizeof(res_type_test)-1, 00180 (uint8_t*)res_type_test, (uint8_t*) res_model_number_val, 00181 sizeof(res_model_number_val)-1, data_item->handle); 00182 00183 CREATE_DYNAMIC_RESOURCE(resource_ptr, sizeof(res_temp)-1, (uint8_t*) res_temp, sizeof(res_type_test)-1, 00184 (uint8_t*)res_type_test, 0, &general_resource_cb, data_item->handle) 00185 00186 /* Start registration */ 00187 if(sn_nsdl_register_endpoint(data_item->handle, data_item->endpoint_ptr) == SN_NSDL_FAILURE) { 00188 printf("NSP registration failed, thread:%d\n", data_item->thread_id); 00189 } 00190 00191 /* Free resource_ptr */ 00192 if(resource_ptr->resource_parameters_ptr) { 00193 own_free(resource_ptr->resource_parameters_ptr); 00194 } 00195 if(resource_ptr) { 00196 own_free(resource_ptr); 00197 } 00198 00199 /* Main loop. */ 00200 /* Listen and process incoming messages */ 00201 while (1) 00202 { 00203 usleep(100); 00204 memset(buf, 0, BUFLEN); 00205 rcv_size = receive_msg(data_item,buf); 00206 if(rcv_size > 0) { 00207 sn_nsdl_process_coap(data_item->handle, buf, rcv_size, &data_item->received_packet_address); 00208 } 00209 } 00210 return 0; 00211 } 00212 00213 int16_t receive_msg(thread_data_struct_s *data_item, uint8_t *buf) 00214 { 00215 char rcv_in_addr[32]; 00216 int16_t rcv_size=0; 00217 00218 memset(rcv_in_addr,0,32); 00219 00220 if ((rcv_size=recvfrom(data_item->sock_server, buf, BUFLEN, 0, 00221 (struct sockaddr *)&data_item->sa_dst, (socklen_t*)&data_item->slen_sa_dst))==-1) { 00222 stop_pgm("recvfrom()"); 00223 } 00224 else { 00225 inet_ntop(AF_INET, &(data_item->sa_dst.sin_addr),rcv_in_addr,INET_ADDRSTRLEN); 00226 data_item->received_packet_address.port = ntohs(data_item->sa_dst.sin_port); 00227 data_item->received_packet_address.type = SN_NSDL_ADDRESS_TYPE_IPV4; 00228 data_item->received_packet_address.addr_len = 4; 00229 memcpy(data_item->received_packet_address.addr_ptr, &data_item->sa_dst.sin_addr, 4); 00230 printf("\nRX %s.%d [%d B] - thread id: %d\n", rcv_in_addr, ntohs(data_item->sa_dst.sin_port), rcv_size, data_item->thread_id); 00231 } 00232 return rcv_size; 00233 } 00234 00235 /* Function needed for libCoap protocol. */ 00236 uint8_t tx_function(struct nsdl_s *handle, sn_nsdl_capab_e protocol, 00237 uint8_t *data, uint16_t len, sn_nsdl_addr_s *address) 00238 { 00239 /* Set NSP address and port */ 00240 thread_data_struct_s *data_item = NULL; 00241 ns_list_foreach(thread_data_struct_s, item, &data_list) { 00242 if (item->handle == handle) { 00243 data_item = item; 00244 break; 00245 } 00246 } 00247 00248 if (data_item != NULL) { 00249 printf("TX function - thread id: %d\n", data_item->thread_id); 00250 ns_list_remove(&data_list, data_item); 00251 data_item->sa_dst.sin_family = AF_INET; 00252 data_item->sa_dst.sin_port = htons(address->port); 00253 memcpy(&data_item->sa_dst.sin_addr, address->addr_ptr, address->addr_len); 00254 ns_list_add_to_end(&data_list, data_item); 00255 00256 int ret = sendto(data_item->sock_server, 00257 data, 00258 len, 00259 0, 00260 (const struct sockaddr *)&data_item->sa_dst, 00261 data_item->slen_sa_dst); 00262 if (ret == -1) { 00263 stop_pgm("sendto() failed"); 00264 } 00265 } 00266 return 1; 00267 } 00268 00269 /* RX function for libNsdl. Passes CoAP responses sent from application to this function. Also response to registration message */ 00270 uint8_t rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_header, sn_nsdl_addr_s *address) 00271 { 00272 if(!coap_header) 00273 return 0; 00274 00275 thread_data_struct_s *data_item = NULL; 00276 ns_list_foreach(thread_data_struct_s, item, &data_list) { 00277 if (item->handle == handle) { 00278 data_item = item; 00279 break; 00280 } 00281 } 00282 if (!data_item) 00283 return 0; 00284 printf("\nRX callback mid:%d, thread id: %d\n", coap_header->msg_id, data_item->thread_id); 00285 00286 /* If message is response to NSP registration */ 00287 if(coap_header->msg_code == COAP_MSG_CODE_RESPONSE_CREATED && 00288 !data_item->registered) { 00289 reg_location_len = coap_header->options_list_ptr->location_path_len; 00290 if(reg_location) 00291 free(reg_location); 00292 reg_location = malloc(reg_location_len); 00293 00294 if(!reg_location) { 00295 return 0; 00296 } 00297 00298 memcpy(reg_location, coap_header->options_list_ptr->location_path_ptr, reg_location_len); 00299 printf("Registered to NSP: "); 00300 for(int i = 0; i < reg_location_len; i++) 00301 printf("%c", *(reg_location+i)); 00302 printf("\n"); 00303 00304 data_item->registered = true; 00305 } 00306 return 0; 00307 } 00308 00309 static void ctrl_c_handle_function() 00310 { 00311 printf("Pressed ctrl-c\n"); 00312 ns_list_foreach(thread_data_struct_s, item, &data_list) { 00313 if (item->handle) { 00314 sn_nsdl_unregister_endpoint(item->handle); 00315 } 00316 } 00317 if(reg_location) 00318 own_free(reg_location); 00319 exit(1); 00320 } 00321 00322 void coap_exec_poll_function(int thread_id) 00323 { 00324 uint8_t i = 0; 00325 sn_coap_hdr_s coap_header; 00326 00327 while(1) 00328 { 00329 sleep(1); 00330 thread_data_struct_s *data_item = NULL; 00331 ns_list_foreach(thread_data_struct_s, item, &data_list) { 00332 if (item->thread_id == thread_id) { 00333 data_item = item; 00334 break; 00335 } 00336 } 00337 if (data_item) { 00338 /* nsdl execution function, must be called at least once / second. System time must be increased every second. */ 00339 /* Cleans saved and unused data from libraries. Recommend to run this in same thread with other nsdl - functions */ 00340 sn_nsdl_exec(data_item->handle, data_item->ns_system_time); 00341 data_item->ns_system_time++; 00342 00343 /* Check if reregistration needed */ 00344 if(!(data_item->ns_system_time % (uint32_t)30) && data_item->ns_system_time) 00345 { 00346 printf("Update registration - thread id: %d\n", data_item->thread_id); 00347 sn_nsdl_update_registration(data_item->handle, data_item->endpoint_ptr->lifetime_ptr, data_item->endpoint_ptr->lifetime_len); 00348 } 00349 00350 /* Send delayed response to request */ 00351 /* This is just example. When receiving request to sen/temp, application send ack and after few seconds value for this resource */ 00352 if(data_item->delayed_response_cnt == 1) { 00353 printf("Delayed response - thread: %d\n", data_item->thread_id); 00354 memset(&coap_header, 0, sizeof(sn_coap_hdr_s)); 00355 00356 if(data_item->delayed_msg_type == COAP_MSG_TYPE_CONFIRMABLE) 00357 coap_header.msg_type = COAP_MSG_TYPE_CONFIRMABLE; 00358 else if(data_item->delayed_msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) 00359 coap_header.msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; 00360 00361 coap_header.msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; 00362 00363 if(data_item->delayed_token_len) 00364 { 00365 coap_header.token_len = data_item->delayed_token_len; 00366 coap_header.token_ptr = data_item->delayed_token; 00367 data_item->delayed_token_len = 0; 00368 } 00369 00370 coap_header.payload_len = sizeof(data_item->res_temp_val) - 1; 00371 coap_header.payload_ptr = data_item->res_temp_val; 00372 00373 sn_nsdl_send_coap_message(data_item->handle, &data_item->received_packet_address, &coap_header); 00374 00375 data_item->delayed_response_cnt = 0; 00376 00377 } 00378 else if(data_item->delayed_response_cnt > 1) { 00379 data_item->delayed_response_cnt--; 00380 } 00381 } 00382 } 00383 } 00384 00385 /* This is callback for other DYNAMIC resources */ 00386 uint8_t general_resource_cb(struct nsdl_s *handle, sn_coap_hdr_s *received_coap_ptr, 00387 sn_nsdl_addr_s *address, sn_nsdl_capab_e protocol) 00388 { 00389 sn_coap_hdr_s *coap_res_ptr = 0; 00390 thread_data_struct_s *data_item = NULL; 00391 ns_list_foreach(thread_data_struct_s, item, &data_list) { 00392 if (item->handle == handle) { 00393 data_item = item; 00394 break; 00395 } 00396 } 00397 if (!data_item) { 00398 return 0; 00399 } 00400 00401 if (received_coap_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) { 00402 printf("\nGeneral callback - thread id: %d\n", data_item->thread_id); 00403 coap_res_ptr = sn_nsdl_build_response(data_item->handle, received_coap_ptr, COAP_MSG_CODE_RESPONSE_CONTENT); 00404 coap_res_ptr->content_type_ptr = &text_plain; 00405 coap_res_ptr->content_type_len = sizeof(text_plain); 00406 00407 /* Temperature resource */ 00408 /* This makes delayed response, first ack and after that real value */ 00409 if(compare_uripaths(received_coap_ptr, res_temp)) 00410 { 00411 send_ack(data_item->handle,received_coap_ptr, &data_item->received_packet_address); 00412 if(coap_res_ptr->token_ptr) { 00413 own_free(coap_res_ptr->token_ptr); 00414 } 00415 if(coap_res_ptr->options_list_ptr) { 00416 own_free(coap_res_ptr->options_list_ptr); 00417 } 00418 own_free(coap_res_ptr); 00419 return 0; 00420 } 00421 sn_nsdl_send_coap_message(data_item->handle, address, coap_res_ptr); 00422 } 00423 else if (received_coap_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) { 00424 if (received_coap_ptr->payload_ptr && received_coap_ptr->payload_len < 16) { 00425 ns_list_remove(&data_list, data_item); 00426 memcpy(data_item->res_temp_val,received_coap_ptr->payload_ptr, received_coap_ptr->payload_len); 00427 printf("Update resource value to %s, thread id: %d\n", data_item->res_temp_val, data_item->thread_id); 00428 ns_list_add_to_end(&data_list, data_item); 00429 } 00430 coap_res_ptr = sn_nsdl_build_response(data_item->handle, received_coap_ptr, COAP_MSG_CODE_RESPONSE_CHANGED); 00431 sn_nsdl_send_coap_message(data_item->handle, address, coap_res_ptr); 00432 } 00433 /* Method not supported */ 00434 else { 00435 printf("Method not supported\n"); 00436 coap_res_ptr = sn_coap_build_response(handle->grs->coap, received_coap_ptr, COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED); 00437 sn_nsdl_send_coap_message(handle, address, coap_res_ptr); 00438 } 00439 00440 if(coap_res_ptr->token_ptr) { 00441 own_free(coap_res_ptr->token_ptr); 00442 } 00443 00444 if(coap_res_ptr->options_list_ptr) { 00445 own_free(coap_res_ptr->options_list_ptr); 00446 } 00447 own_free(coap_res_ptr); 00448 00449 return 0; 00450 } 00451 00452 int8_t compare_uripaths(sn_coap_hdr_s *coap_header, const uint8_t *uri_path_to_compare) 00453 { 00454 if(memcmp(coap_header->uri_path_ptr,&uri_path_to_compare[0], coap_header->uri_path_len) == 0) 00455 { 00456 return 1; 00457 } 00458 return 0; 00459 } 00460 00461 void send_ack(struct nsdl_s *handle, sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address/*, sn_nsdl_addr_s *received_packet_address*/) 00462 { 00463 printf("Send acknowledgement\n"); 00464 sn_coap_hdr_s *coap_res_ptr = 0; 00465 uint16_t message_len = 0; 00466 uint8_t *message_ptr; 00467 thread_data_struct_s *data_item = NULL; 00468 ns_list_foreach(thread_data_struct_s, item, &data_list) { 00469 if (item->handle == handle) { 00470 data_item = item; 00471 break; 00472 } 00473 } 00474 if (data_item) { 00475 if (received_coap_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) 00476 { 00477 if (received_coap_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { 00478 coap_res_ptr = own_alloc(sizeof(sn_coap_hdr_s)); 00479 if(!coap_res_ptr) { 00480 return; 00481 } 00482 memset(coap_res_ptr, 0x00, sizeof(sn_coap_hdr_s)); 00483 coap_res_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; 00484 coap_res_ptr->msg_code = COAP_MSG_CODE_EMPTY; 00485 coap_res_ptr->msg_id = received_coap_ptr->msg_id; 00486 data_item->delayed_msg_type = COAP_MSG_TYPE_CONFIRMABLE; 00487 } 00488 else { 00489 data_item->delayed_msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; 00490 } 00491 00492 if(received_coap_ptr->token_len) { 00493 memset(data_item->delayed_token, 0, 8); 00494 data_item->delayed_token_len = received_coap_ptr->token_len; 00495 memcpy(data_item->delayed_token, received_coap_ptr->token_ptr, received_coap_ptr->token_len); 00496 } 00497 data_item->delayed_response_cnt = 1; 00498 } 00499 } 00500 00501 if(coap_res_ptr) { 00502 message_len = sn_coap_builder_calc_needed_packet_data_size(coap_res_ptr); 00503 message_ptr = own_alloc(message_len); 00504 if(!message_ptr) { 00505 return; 00506 } 00507 00508 sn_coap_builder(message_ptr, coap_res_ptr); 00509 tx_function(handle,SN_NSDL_PROTOCOL_COAP, message_ptr, message_len, address); 00510 00511 /* Free memory */ 00512 if(coap_res_ptr) { 00513 own_free(coap_res_ptr); 00514 } 00515 own_free(message_ptr); 00516 } 00517 return; 00518 }
Generated on Tue Jul 12 2022 12:28:42 by
