static void notify_all_led3_subscribers(coap_msg_type_t type) { // Fetch all observers which are subscribed to this resource. // Then send an update value too each observer. coap_observer_t * p_observer = NULL; while (coap_observe_server_next_get(&p_observer, p_observer, &m_led3) == NRF_SUCCESS) { // Generate a message. coap_message_conf_t response_config; memset(&response_config, 0, sizeof(coap_message_conf_t)); response_config.type = type; response_config.code = COAP_CODE_205_CONTENT; response_config.response_callback = observer_con_message_callback; // Copy token. memcpy(&response_config.token[0], &p_observer->token[0], p_observer->token_len); // Copy token length. response_config.token_len = p_observer->token_len; response_config.port.port_number = COAP_SERVER_PORT; coap_message_t * p_response; uint32_t err_code = coap_message_new(&p_response, &response_config); APP_ERROR_CHECK(err_code); // Set custom misc. argument. p_response->p_arg = p_observer; err_code = coap_message_remote_addr_set(p_response, &p_observer->remote); APP_ERROR_CHECK(err_code); err_code = coap_message_opt_uint_add(p_response, COAP_OPT_OBSERVE, m_observer_sequence_num++); APP_ERROR_CHECK(err_code); err_code = coap_message_opt_uint_add(p_response, COAP_OPT_MAX_AGE, m_led3.expire_time); APP_ERROR_CHECK(err_code); char * response_str; led_value_get(p_observer->ct, &response_str); err_code = coap_message_payload_set(p_response, response_str, strlen(response_str)); APP_ERROR_CHECK(err_code); uint32_t msg_handle; err_code = coap_message_send(&msg_handle, p_response); APP_ERROR_CHECK(err_code); err_code = coap_message_delete(p_response); APP_ERROR_CHECK(err_code); } }
void well_known_core_callback(coap_resource_t * p_resource, coap_message_t * p_request) { coap_message_conf_t response_config; memset(&response_config, 0x00, sizeof(coap_message_conf_t)); if (p_request->header.type == COAP_TYPE_NON) { response_config.type = COAP_TYPE_NON; } else if (p_request->header.type == COAP_TYPE_CON) { response_config.type = COAP_TYPE_ACK; } // PIGGY BACKED RESPONSE response_config.code = COAP_CODE_205_CONTENT; // Copy message ID. response_config.id = p_request->header.id; // Set local port number to use. response_config.port.port_number = LOCAL_PORT_NUM; // Copy token. memcpy(&response_config.token[0], &p_request->token[0], p_request->header.token_len); // Copy token length. response_config.token_len = p_request->header.token_len; coap_message_t * p_response; uint32_t err_code = coap_message_new(&p_response, &response_config); APP_ERROR_CHECK(err_code); err_code = coap_message_remote_addr_set(p_response, &p_request->remote); APP_ERROR_CHECK(err_code); memcpy(&p_response->remote, &p_request->remote, sizeof(coap_remote_t)); err_code = coap_message_opt_uint_add(p_response, COAP_OPT_CONTENT_FORMAT, \ COAP_CT_APP_LINK_FORMAT); APP_ERROR_CHECK(err_code); err_code = coap_message_payload_set(p_response, m_well_known_core, \ strlen((char *)m_well_known_core)); APP_ERROR_CHECK(err_code); uint32_t msg_handle; err_code = coap_message_send(&msg_handle, p_response); APP_ERROR_CHECK(err_code); err_code = coap_message_delete(p_response); APP_ERROR_CHECK(err_code); }
static void handle_led_request(uint32_t led_mask, coap_message_t * p_request, coap_resource_t * p_resource) { coap_message_conf_t response_config; memset(&response_config, 0x00, sizeof(coap_message_conf_t)); if (p_request->header.type == COAP_TYPE_NON) { response_config.type = COAP_TYPE_NON; } else if (p_request->header.type == COAP_TYPE_CON) { response_config.type = COAP_TYPE_ACK; } // PIGGY BACKED RESPONSE response_config.code = COAP_CODE_405_METHOD_NOT_ALLOWED; // Copy message ID. response_config.id = p_request->header.id; // Set local port number to use. response_config.port.port_number = LOCAL_PORT_NUM; // Copy token. memcpy(&response_config.token[0], &p_request->token[0], p_request->header.token_len); // Copy token length. response_config.token_len = p_request->header.token_len; coap_message_t * p_response; uint32_t err_code = coap_message_new(&p_response, &response_config); APP_ERROR_CHECK(err_code); err_code = coap_message_remote_addr_set(p_response, &p_request->remote); APP_ERROR_CHECK(err_code); // Handle request. switch (p_request->header.code) { case COAP_CODE_GET: { p_response->header.code = COAP_CODE_205_CONTENT; // Select the first common content-type between the resource and the CoAP client. coap_content_type_t ct_to_use; err_code = coap_message_ct_match_select(&ct_to_use, p_request, p_resource); if (err_code != NRF_SUCCESS) { // None of the accept content formats are supported in this resource endpoint. p_response->header.code = COAP_CODE_415_UNSUPPORTED_CONTENT_FORMAT; p_response->header.type = COAP_TYPE_RST; } else { // Set response payload to actual LED state. char * response_str; led_value_get(led_mask, ct_to_use, &response_str); err_code = coap_message_payload_set(p_response, response_str, strlen(response_str)); APP_ERROR_CHECK(err_code); } break; } case COAP_CODE_PUT: { p_response->header.code = COAP_CODE_204_CHANGED; // Change LED state according to request. switch (p_request->p_payload[0]) { case COMMAND_ON: { LEDS_ON(led_mask); break; } case COMMAND_OFF: { LEDS_OFF(led_mask); break; } case COMMAND_TOGGLE: { LEDS_INVERT(led_mask); break; } default: { p_response->header.code = COAP_CODE_400_BAD_REQUEST; break; } } break; } default: { p_response->header.code = COAP_CODE_405_METHOD_NOT_ALLOWED; break; } } uint32_t msg_handle; err_code = coap_message_send(&msg_handle, p_response); APP_ERROR_CHECK(err_code); err_code = coap_message_delete(p_response); APP_ERROR_CHECK(err_code); }
static void led3_callback(coap_resource_t * p_resource, coap_message_t * p_request) { coap_message_conf_t response_config; memset (&response_config, 0, sizeof(coap_message_conf_t)); if (p_request->header.type == COAP_TYPE_NON) { response_config.type = COAP_TYPE_NON; } else if (p_request->header.type == COAP_TYPE_CON) { response_config.type = COAP_TYPE_ACK; } // PIGGY BACKED RESPONSE response_config.code = COAP_CODE_405_METHOD_NOT_ALLOWED; // Copy message ID. response_config.id = p_request->header.id; // Copy token. memcpy(&response_config.token[0], &p_request->token[0], p_request->header.token_len); // Copy token length. response_config.token_len = p_request->header.token_len; coap_message_t * p_response; uint32_t err_code = coap_message_new(&p_response, &response_config); APP_ERROR_CHECK(err_code); err_code = coap_message_remote_addr_set(p_response, &p_request->remote); APP_ERROR_CHECK(err_code); // Handle request. switch (p_request->header.code) { case COAP_CODE_GET: { p_response->header.code = COAP_CODE_205_CONTENT; // Select the first common content type between the resource and the CoAP client. coap_content_type_t ct_to_use; err_code = coap_message_ct_match_select(&ct_to_use, p_request, p_resource); if (err_code != NRF_SUCCESS) { // None of the accepted content formats are supported in this resource endpoint. p_response->header.code = COAP_CODE_415_UNSUPPORTED_CONTENT_FORMAT; p_response->header.type = COAP_TYPE_RST; } else { if (coap_message_opt_present(p_request, COAP_OPT_OBSERVE) == NRF_SUCCESS) { // Locate the option and check the value. uint32_t observe_option = 0; uint8_t index; for (index = 0; index < p_request->options_count; index++) { if (p_request->options[index].number == COAP_OPT_OBSERVE) { err_code = coap_opt_uint_decode(&observe_option, p_request->options[index].length, p_request->options[index].p_data); if (err_code != NRF_SUCCESS) { APP_ERROR_CHECK(err_code); } break; } } if (observe_option == 0) { // Register observer, and if successful, add the Observe option in the reply. uint32_t handle; coap_observer_t observer; // Set the token length. observer.token_len = p_request->header.token_len; // Set the resource of interest. observer.p_resource_of_interest = p_resource; // Set the remote. memcpy(&observer.remote, &p_request->remote, sizeof(coap_remote_t)); // Set the token. memcpy(observer.token, p_request->token, observer.token_len); // Set the content format to be used for subsequent notifications. observer.ct = ct_to_use; err_code = coap_observe_server_register(&handle, &observer); if (err_code == NRF_SUCCESS) { err_code = coap_message_opt_uint_add(p_response, COAP_OPT_OBSERVE, m_observer_sequence_num++); APP_ERROR_CHECK(err_code); err_code = coap_message_opt_uint_add(p_response, COAP_OPT_MAX_AGE, p_resource->expire_time); APP_ERROR_CHECK(err_code); } // If the registration of the observer could not be done, handle this as a normal message. } else { uint32_t handle; err_code = coap_observe_server_search(&handle, &p_request->remote, p_resource); if (err_code == NRF_SUCCESS) { err_code = coap_observe_server_unregister(handle); APP_ERROR_CHECK(err_code); } } } // Set response payload to the actual LED state. char * response_str; led_value_get(ct_to_use, &response_str); err_code = coap_message_payload_set(p_response, response_str, strlen(response_str)); APP_ERROR_CHECK(err_code); } break; } case COAP_CODE_PUT: { p_response->header.code = COAP_CODE_204_CHANGED; // Change LED state according to request. switch (p_request->p_payload[0]) { case COMMAND_ON: { LEDS_ON(LED_THREE); break; } case COMMAND_OFF: { LEDS_OFF(LED_THREE); break; } case COMMAND_TOGGLE: { LEDS_INVERT(LED_THREE); break; } default: { p_response->header.code = COAP_CODE_400_BAD_REQUEST; break; } } break; } default: { p_response->header.code = COAP_CODE_405_METHOD_NOT_ALLOWED; break; } } uint32_t msg_handle; err_code = coap_message_send(&msg_handle, p_response); APP_ERROR_CHECK(err_code); err_code = coap_message_delete(p_response); APP_ERROR_CHECK(err_code); if (p_request->header.code == COAP_CODE_PUT) { notify_all_led3_subscribers(COAP_TYPE_NON); } }
/**@brief Function for handling button events. * * @param[in] pin_no The pin number of the button pressed. * @param[in] button_action The action performed on button. */ static void button_event_handler(uint8_t pin_no, uint8_t button_action) { if(mp_interface == NULL) { return; } uint32_t err_code; if (button_action == APP_BUTTON_PUSH) { coap_message_t * p_request = NULL; switch (pin_no) { case BUTTON_ONE: { coap_message_conf_t message_conf; coap_remote_t remote_device; message_conf.type = COAP_MESSAGE_TYPE; message_conf.code = COAP_CODE_GET; message_conf.id = 0; // Set token. m_led3_observe_token = m_global_token_count; (void)uint16_encode(HTONS(m_global_token_count), message_conf.token); m_global_token_count++; message_conf.token_len = 2; message_conf.response_callback = coap_response_handler; err_code = coap_message_new(&p_request, &message_conf); APP_ERROR_CHECK(err_code); memcpy(&remote_device.addr[0], (uint8_t []){SERVER_IPV6_ADDRESS}, IPV6_ADDR_SIZE); remote_device.port_number = SERVER_PORT_NUM; err_code = coap_message_remote_addr_set(p_request, &remote_device); APP_ERROR_CHECK(err_code); // Subscribe to the resource. err_code = coap_message_opt_uint_add(p_request, COAP_OPT_OBSERVE, 0); APP_ERROR_CHECK(err_code); err_code = coap_message_opt_str_add(p_request, COAP_OPT_URI_PATH, (uint8_t *)m_uri_part_lights, strlen(m_uri_part_lights)); APP_ERROR_CHECK(err_code); err_code = coap_message_opt_str_add(p_request, COAP_OPT_URI_PATH, (uint8_t *)m_uri_part_led3, strlen(m_uri_part_led3)); APP_ERROR_CHECK(err_code); err_code = coap_message_opt_uint_add(p_request, COAP_OPT_ACCEPT, 0); APP_ERROR_CHECK(err_code); break; } case BUTTON_TWO: { coap_message_conf_t message_conf; coap_remote_t remote_device; message_conf.type = COAP_MESSAGE_TYPE; message_conf.code = COAP_CODE_GET; message_conf.id = 0; // Re-use the original token for the observe. (void)uint16_encode(HTONS(m_led3_observe_token), message_conf.token); message_conf.token_len = 2; message_conf.response_callback = coap_response_handler; err_code = coap_message_new(&p_request, &message_conf); APP_ERROR_CHECK(err_code); memcpy(&remote_device.addr[0], (uint8_t []){SERVER_IPV6_ADDRESS}, IPV6_ADDR_SIZE); remote_device.port_number = SERVER_PORT_NUM; err_code = coap_message_remote_addr_set(p_request, &remote_device); APP_ERROR_CHECK(err_code); // Unsubscribe to the resource. err_code = coap_message_opt_uint_add(p_request, COAP_OPT_OBSERVE, 1); APP_ERROR_CHECK(err_code); // Copy the original options (draft-ietf-core-observe 3.6). err_code = coap_message_opt_str_add(p_request, COAP_OPT_URI_PATH, (uint8_t *)m_uri_part_lights, strlen(m_uri_part_lights)); APP_ERROR_CHECK(err_code); err_code = coap_message_opt_str_add(p_request, COAP_OPT_URI_PATH, (uint8_t *)m_uri_part_led3, strlen(m_uri_part_led3)); APP_ERROR_CHECK(err_code); err_code = coap_message_opt_uint_add(p_request, COAP_OPT_ACCEPT, 0); APP_ERROR_CHECK(err_code); break; } default: break; } // TODO: If there is no more room for subscribing to observable resources, we should // remove the observable option before sending the message. if (p_request != NULL) { uint32_t msg_handle; err_code = coap_message_send(&msg_handle, p_request); if (err_code != NRF_SUCCESS) { APPL_LOG("[APPL]: CoAP Message skipped, error code = 0x%08lX.\r\n", err_code); } err_code = coap_message_delete(p_request); APP_ERROR_CHECK(err_code); } }