Esempio n. 1
0
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);
}
Esempio n. 4
0
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);
    }
}
Esempio n. 5
0
/**@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);
        }
    }