Exemple #1
0
void
http_get_task(void *pvParameters)
{
    coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */
    int failures = 0;

    // create network socket
    struct addrinfo hints;
    struct addrinfo *res;

    // Use an UDP socket
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;

    // Get host/port from request URL
    // should call free(uri) somewhere
    coap_uri_t *uri = coap_new_uri((unsigned char*)URI, strlen(URI));   
    if (uri == NULL) {
        COAP_PRINTF("coap_new_uri(): URI failed\n");
        vTaskDelete(NULL);
    }

    // DNS lookup
    int err;
    char port[6];
    char host[32];
    char path[64];

    sprintf(port, "%d", uri->port);
    sprintf(path, "%s", uri->path.s);
    memcpy(host, uri->host.s, uri->host.length);
    host[uri->host.length] = '\0';

    COAP_PRINTF("URI Path: %s\n", path);
    COAP_PRINTF("URI Host: %s\n", host);
    COAP_PRINTF("URI Port: %s\n", port);

    printf("Running DNS lookup for %s...\r\n", host);

    while (1) {
        err = getaddrinfo(host, port, &hints, &res);
        if (err == 0)
            break;
        freeaddrinfo(res);
        printf("DNS lookup failed err=%d res=%p\r\n", err, res);
        vTaskDelay(3000 / portTICK_RATE_MS);
    }

    /* Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
    struct in_addr *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
    char *ip = inet_ntoa(*addr);
    printf("DNS lookup succeeded. HOST=%s, IP=%s\r\n", host, ip);

    // init a HTTP POST message and set message header
    coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0);
    coap_set_header_uri_path(request, path);
    coap_set_header_uri_host(request, host);

    // Create a local socket
    int s = socket(res->ai_family, res->ai_socktype, 0);
    if(s < 0) {
        printf("... Failed to allocate socket.\r\n");
        freeaddrinfo(res);
        vTaskDelete(NULL);
    }

    printf("... allocated socket\r\n");

    int a;
    int ret;
    char payload[128];
    struct request_state_t state[1];
    ip_addr_t ipaddr;

    ipaddr.addr = ipaddr_addr(ip);

    while(1) {
        if(connect(s, res->ai_addr, res->ai_addrlen) != 0) {
            close(s);
            freeaddrinfo(res);
            printf("... socket connect failed.\r\n");
            vTaskDelay(3000 / portTICK_RATE_MS);
            failures++;
            continue;
        }

        printf("... connected\r\n");
        freeaddrinfo(res);
repeat:
        vTaskDelay(5000 / portTICK_RATE_MS);

        // read sensor data from ESP8266 A0
        a = sdk_system_adc_read();

        sprintf(payload, "{ \"quality\": %d }\n", a);
        COAP_PRINTF("Payload: %s\n", payload);

        // CoAP payload
        coap_set_payload(request, payload, strlen(payload));

        // Make CoAP transaction
        request->mid = coap_get_mid();

        if ((state->transaction = coap_new_transaction(request->mid, &ipaddr, uri->port)))
        {
            state->transaction->callback = coap_blocking_request_callback;
            state->transaction->callback_data = state;

            if (state->block_num > 0)
            {
                coap_set_header_block2(request, state->block_num, 0, REST_MAX_CHUNK_SIZE);
            }

            // Build CoAP header and Options
            state->transaction->packet_len = coap_serialize_message(request, state->transaction->packet);

            COAP_PRINTF("Header dump: [0x%02X %02X %02X %02X]. Size: %d\n",
                request->buffer[0],
                request->buffer[1],
                request->buffer[2],
                request->buffer[3],
                state->transaction->packet_len
            );

            COAP_PRINTF("Requested #%u (MID %u)\n", state->block_num, request->mid);

            // Transmit
            ret = write(s, state->transaction->packet, state->transaction->packet_len);
            //ret = sendto(s, state->transaction->packet, state->transaction->packet_len);
            if (ret < 0) {
                printf("[RET: %d] CoAP packet send failed.\n", ret);
                continue;
            }
        }
        else
        {
          COAP_PRINTF("Could not allocate transaction buffer");
        }

        goto repeat;
    }
}
void
mirror_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
  /* The ETag and Token is copied to the header. */
  uint8_t opaque[] = {0x0A, 0xBC, 0xDE};

  /* Strings are not copied, so use static string buffers or strings in .text memory (char *str = "string in .text";). */
  static char location[] = {'/','f','/','a','?','k','&','e', 0};

  /* Getter for the header option Content-Type. If the option is not set, text/plain is returned by default. */
  unsigned int content_type = REST.get_header_content_type(request);

  /* The other getters copy the value (or string/array pointer) to the given pointers and return 1 for success or the length of strings/arrays. */
  uint32_t max_age_and_size = 0;
  const char *str = NULL;
  uint32_t observe = 0;
  const uint8_t *bytes = NULL;
  uint32_t block_num = 0;
  uint8_t block_more = 0;
  uint16_t block_size = 0;
  const char *query = "";
  int len = 0;

  /* Mirror the received header options in the response payload. Unsupported getters (e.g., rest_get_header_observe() with HTTP) will return 0. */

  int strpos = 0;
  /* snprintf() counts the terminating '\0' to the size parameter.
   * The additional byte is taken care of by allocating REST_MAX_CHUNK_SIZE+1 bytes in the REST framework.
   * Add +1 to fill the complete buffer, as the payload does not need a terminating '\0'. */
  if (content_type!=-1)
  {
    strpos += snprintf((char *)buffer, REST_MAX_CHUNK_SIZE+1, "CT %u\n", content_type);
  }
  
  /* Some getters such as for ETag or Location are omitted, as these options should not appear in a request.
   * Max-Age might appear in HTTP requests or used for special purposes in CoAP. */
  if (strpos<=REST_MAX_CHUNK_SIZE && REST.get_header_max_age(request, &max_age_and_size))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "MA %lu\n", max_age_and_size);
  }
  /* For HTTP this is the Length option, for CoAP it is the Size option. */
  if (strpos<=REST_MAX_CHUNK_SIZE && REST.get_header_length(request, &max_age_and_size))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "SZ %lu\n", max_age_and_size);
  }

  if (strpos<=REST_MAX_CHUNK_SIZE && (len = REST.get_header_host(request, &str)))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "UH %.*s\n", len, str);
  }

/* CoAP-specific example: actions not required for normal RESTful Web service. */
#if WITH_COAP > 1
  if (strpos<=REST_MAX_CHUNK_SIZE && coap_get_header_observe(request, &observe))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "Ob %lu\n", observe);
  }
  if (strpos<=REST_MAX_CHUNK_SIZE && (len = coap_get_header_token(request, &bytes)))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "To 0x");
    int index = 0;
    for (index = 0; index<len; ++index) {
        strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "%02X", bytes[index]);
    }
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "\n");
  }
  if (strpos<=REST_MAX_CHUNK_SIZE && (len = coap_get_header_etag(request, &bytes)))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "ET 0x");
    int index = 0;
    for (index = 0; index<len; ++index) {
        strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "%02X", bytes[index]);
    }
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "\n");
  }
  if (strpos<=REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_path(request, &str)))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "UP ");
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "%.*s\n", len, str);
  }
#if WITH_COAP == 3
  if (strpos<=REST_MAX_CHUNK_SIZE && (len = coap_get_header_location(request, &str)))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "Lo %.*s\n", len, str);
  }
  if (strpos<=REST_MAX_CHUNK_SIZE && coap_get_header_block(request, &block_num, &block_more, &block_size, NULL)) /* This getter allows NULL pointers to get only a subset of the block parameters. */
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "Bl %lu%s (%u)\n", block_num, block_more ? "+" : "", block_size);
  }
#else
  if (strpos<=REST_MAX_CHUNK_SIZE && (len = coap_get_header_location_path(request, &str)))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "LP %.*s\n", len, str);
  }
  if (strpos<=REST_MAX_CHUNK_SIZE && (len = coap_get_header_location_query(request, &str)))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "LQ %.*s\n", len, str);
  }
  if (strpos<=REST_MAX_CHUNK_SIZE && coap_get_header_block2(request, &block_num, &block_more, &block_size, NULL)) /* This getter allows NULL pointers to get only a subset of the block parameters. */
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "B2 %lu%s (%u)\n", block_num, block_more ? "+" : "", block_size);
  }
  /*
   * Critical Block1 option is currently rejected by engine.
   *
  if (strpos<=REST_MAX_CHUNK_SIZE && coap_get_header_block1(request, &block_num, &block_more, &block_size, NULL))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "B1 %lu%s (%u)\n", block_num, block_more ? "+" : "", block_size);
  }
  */
#endif /* CoAP > 03 */
#endif /* CoAP-specific example */

  if (strpos<=REST_MAX_CHUNK_SIZE && (len = REST.get_query(request, &query)))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "Qu %.*s\n", len, query);
  }
  if (strpos<=REST_MAX_CHUNK_SIZE && (len = REST.get_request_payload(request, &bytes)))
  {
    strpos += snprintf((char *)buffer+strpos, REST_MAX_CHUNK_SIZE-strpos+1, "%.*s", len, bytes);
  }

  if (strpos >= REST_MAX_CHUNK_SIZE)
  {
      buffer[REST_MAX_CHUNK_SIZE-1] = 0xBB; /* '»' to indicate truncation */
  }

  REST.set_response_payload(response, buffer, strpos);

  PRINTF("/mirror options received: %s\n", buffer);

  /* Set dummy header options for response. Like getters, some setters are not implemented for HTTP and have no effect. */
  REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
  REST.set_header_max_age(response, 17); /* For HTTP, browsers will not re-request the page for 17 seconds. */
  REST.set_header_etag(response, opaque, 2);
  REST.set_header_location(response, location); /* Initial slash is omitted by framework */
  REST.set_header_length(response, strpos); /* For HTTP, browsers will not re-request the page for 10 seconds. CoAP action depends on the client. */

/* CoAP-specific example: actions not required for normal RESTful Web service. */
#if WITH_COAP > 1
  coap_set_header_uri_host(response, "tiki");
  coap_set_header_observe(response, 10);
#if WITH_COAP == 3
  coap_set_header_block(response, 42, 0, 64); /* The block option might be overwritten by the framework when blockwise transfer is requested. */
#else
  coap_set_header_proxy_uri(response, "ftp://x");
  coap_set_header_block2(response, 42, 0, 64); /* The block option might be overwritten by the framework when blockwise transfer is requested. */
  coap_set_header_block1(response, 23, 0, 16);
  coap_set_header_accept(response, TEXT_PLAIN);
  coap_set_header_if_none_match(response);
#endif /* CoAP > 03 */
#endif /* CoAP-specific example */
}
void
transmitTask(void *pvParameters)
{
    struct userdata *user = (struct userdata *)pvParameters;
    coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */

    int a;
    char payload[128];
    int failures = 0;

    // Get host/port from request URL
    // should call free(uri) somewhere
    coap_uri_t *uri = coap_new_uri(SERVER_URI, strlen(SERVER_URI));   
    if (uri == NULL) {
        COAP_PRINTF("coap_new_uri(): URI failed\n");
        vTaskDelete(NULL);
    }

    COAP_PRINTF("URI Path: %s\n", uri->path.s);
    COAP_PRINTF("URI Host: %s\n", uri->host.s);

    // init a HTTP POST message and set message header
    coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0);
    coap_set_header_uri_path(request, (char *)uri->path.s);
    coap_set_header_uri_host(request, (char *)uri->host.s);

    // create network socket
    struct addrinfo hints;
    struct addrinfo *res;

    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;

    // 2. DNS lookup
    int err;
    char port[6];

    sprintf(port, "%d", uri->port);
    printf("Running DNS lookup for %s...\r\n", uri->host.s);

    while (1) {
        err = getaddrinfo((char*)uri->host.s, (char*)port, &hints, &res);
        if (err == 0)
            break;
        freeaddrinfo(res);
        printf("DNS lookup failed err=%d res=%p\r\n", err, res);
        vTaskDelay(3000 / portTICK_RATE_MS);
    }

    /* Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
    struct in_addr *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
    printf("DNS lookup succeeded. IP=%s\r\n", inet_ntoa(*addr));

    // 3. Create a local socket
    int s = socket(res->ai_family, res->ai_socktype, 0);
    if(s < 0) {
        printf("... Failed to allocate socket.\r\n");
        freeaddrinfo(res);
        vTaskDelete(NULL);
    }

    printf("... allocated socket\r\n");

    int ret;

    while(1) {
        // connect to server
        if (connect(s, res->ai_addr, res->ai_addrlen) != 0) {
            close(s);
            freeaddrinfo(res);
            failures++;
            printf("... socket connect failed. tries = %d.\r\n", failures);
            vTaskDelay(4000 / portTICK_RATE_MS);
            continue;
        }

        printf("... connected\r\n");
        freeaddrinfo(res);

repeat:
        xQueueReceive(user->xQueue, &a, portMAX_DELAY);

        sprintf(payload, "{ \"quality\": %d }\n", a);
        COAP_PRINTF("Payload: %s\n", payload);

        // CoAP payload
        coap_set_payload(request, payload, strlen(payload));

        ret = write(s, payload, strlen(payload));
        if (ret >= 0) goto repeat;
    }
}