Summary

In the previous articles I talked about the GE Hackathon, using WICED and CapSense, and finally creating a Particle Photon configuration.  In this article I will show you the WICED HTTP Client firmware which will read the button state and send it via WICED HTTP to the Particle Cloud.  To build this project I will start from the I2C Read firmware that I talked about in this article.

There are two parts of this application

  • The “main” application which reads the buttons and sends a message
  • The “sendMessage” function which builds a WICED HTTP message and sends it to the Particle cloud.

Main Application

I took the code from the previous example (CY3280 –> I2C –> WICED) and only made a few modifications (though I rearranged things a bit to make it easier to look at)

  • I joined the network (line 126)
  • I look up the IP address of the Particle Cloud (line 128)
  • Then I send a HIGH or LOW via the sendMessage function based on the state of the buttons (all the buttons do the same thing)
#include "wiced.h" 
#include <stdlib.h> 

#define I2C_ADDRESS (0x37) 
#define BUTTON_REG (0xAA) 
wiced_semaphore_t buttonPress; // used to signal in ISR to signal main
void application_start( )
{
    wiced_init();                                 // Initialize the WICED device
    wiced_rtos_init_semaphore(&requestSemaphore); // Initialize
    wiced_result_t result;

    wiced_network_up(WICED_STA_INTERFACE, WICED_USE_EXTERNAL_DHCP_SERVER, NULL);

    wiced_hostname_lookup( SERVER_HOST, &ip_address, DNS_TIMEOUT_MS, WICED_STA_INTERFACE );
    wiced_rtos_init_semaphore(&buttonPress);

    // WICED_GPIO_9 is the MBR3 Interrupt Pin
    wiced_gpio_init(WICED_GPIO_9,INPUT_PULL_UP);
    wiced_gpio_input_irq_enable(WICED_GPIO_9, IRQ_TRIGGER_FALLING_EDGE, button_isr, NULL); /* Setup interrupt */

    /* Setup I2C master */
    const wiced_i2c_device_t i2cDevice = {
            .port = WICED_I2C_2,
            .address = I2C_ADDRESS,
            .address_width = I2C_ADDRESS_WIDTH_7BIT,
            .speed_mode = I2C_STANDARD_SPEED_MODE
    };

    wiced_i2c_init(&i2cDevice);

    /* Tx buffer is used to set the offset */
    uint8_t tx_buffer[] = {BUTTON_REG};
    uint8_t buttonStatus;
    while ( 1 )
    {
        wiced_rtos_get_semaphore(&buttonPress,WICED_WAIT_FOREVER);

        // Do this until the MBR3 is alive.  It goes into deep sleep and wakes when you
        // send the first command.
        do {
            result = wiced_i2c_write(&i2cDevice, WICED_I2C_START_FLAG | WICED_I2C_STOP_FLAG, tx_buffer, sizeof(tx_buffer));
        }
        while(result != WICED_SUCCESS);

        result=wiced_i2c_read(&i2cDevice, WICED_I2C_START_FLAG | WICED_I2C_STOP_FLAG, &buttonStatus, sizeof(buttonStatus));
        if(buttonStatus > 0)
        {
            WPRINT_APP_INFO(("Sending On\n"));
            sendMessage("HIGH");
        }
        else
        {
            WPRINT_APP_INFO(("Sending Off\n"));
            sendMessage("LOW");
        }

    }
}

Send Message via WICED HTTP

The WICED HTTP sendMessage function simply

  • Creates a http_client (which is just a mechanism to keep track of an HTTP connection
  • Sets up a connection (lines 77-80)
  • Makes the connection (line 82)
  • Creates the message (line 88) in “application/x-www-form-urlencoded” format
  • Builds the HTTP headers for a HTTP “POST” (lines 90-105)
  • Write the Request (lines 108 –> 112)
  • Waits for the response using semaphore (line 114)
  • Destroys the connection (line 115 –> 116)
#include "wiced_tls.h" 
#include "http_client.h" 
#define SERVER_PORT ( 443 ) 
#define SERVER_HOST "api.particle.io" 
#define SERVER_RESOURCE "/v1/devices/2a001b000347353137323334/digitalwrite" 
#define PARTICLE_ACCESS_TOKEN "1311f9217a60" 
#define DNS_TIMEOUT_MS ( 10000 ) 
#define CONNECT_TIMEOUT_MS ( 3000 ) 
wiced_semaphore_t requestSemaphore; // used to signal request is done static http_client_t client; 
static http_request_t request; 
static http_client_configuration_info_t client_configuration; 
static wiced_ip_address_t ip_address; 

/* void sendMessage - Send HTTP request to turn on or off the LED
 */
void sendMessage( char *state )
{

    http_client_init( &client, WICED_STA_INTERFACE, event_handler, NULL );

    /* configure HTTP client parameters */
    client_configuration.flag = (http_client_configuration_flags_t)(HTTP_CLIENT_CONFIG_FLAG_SERVER_NAME | HTTP_CLIENT_CONFIG_FLAG_MAX_FRAGMENT_LEN);
    client_configuration.server_name = (uint8_t*)SERVER_HOST;
    client_configuration.max_fragment_length = TLS_FRAGMENT_LENGTH_1024;
    http_client_configure(&client, &client_configuration);

    http_client_connect( &client, (const wiced_ip_address_t*)&ip_address, SERVER_PORT, HTTP_USE_TLS, CONNECT_TIMEOUT_MS );

    http_header_field_t header[3]; // Three headers
    char messageBody[128];        // Enough to hold the message body
    char messageLengthBuffer[10]; // Enough to hold the characters for the Content-Length: header

    sprintf(messageBody,"access_token=%s&params=D7%%2C%s",PARTICLE_ACCESS_TOKEN,state);

    header[0].field        = HTTP_HEADER_HOST;
    header[0].field_length = sizeof( HTTP_HEADER_HOST ) - 1;
    header[0].value        = SERVER_HOST;
    header[0].value_length = sizeof( SERVER_HOST ) - 1;

#define MIME_FORM_URL "application/x-www-form-urlencoded"
    header[1].field        = HTTP_HEADER_CONTENT_TYPE;
    header[1].field_length = sizeof( HTTP_HEADER_CONTENT_TYPE ) - 1;
    header[1].value        =  MIME_FORM_URL;
    header[1].value_length = sizeof(  MIME_FORM_URL ) - 1;

    sprintf(messageLengthBuffer," %d",strlen(messageBody)); // Put the message body into the buffer so that you can strlen it
    header[2].field        = HTTP_HEADER_CONTENT_LENGTH;
    header[2].field_length = sizeof( HTTP_HEADER_CONTENT_LENGTH ) - 1;
    header[2].value        =  messageLengthBuffer;
    header[2].value_length = strlen(messageLengthBuffer);

    // Build the HTTP Message
    http_request_init( &request, &client, HTTP_POST, SERVER_RESOURCE, HTTP_1_1 );
    http_request_write_header( &request, &header[0], 3 ); // 3 headers
    http_request_write_end_header( &request );
    http_request_write(&request,(uint8_t*)messageBody,strlen(messageBody));
    http_request_flush( &request );

    wiced_rtos_get_semaphore(&requestSemaphore,10000); // wait up to 10 seconds to close the request and the client
    http_request_deinit(&request);
    http_client_deinit(&client);
}

WICED HTTP Event Handler

The way that the WICED HTTP  executes is that it has a worker thread waiting on the TCP socket.  When it gets a response it runs your callback function and tells you what happened.  In this case I just tell my thread to close the connection and move on.

/*
 * void event_handler() is called by the http_client function when
 *  Data is received from the server
 *  a connection is made
 *  a disconnect occurs
 *
 *  When data is received I assume that the response is good and I reset the semaphore so that another request can happen
 */

static void event_handler( http_client_t* client, http_event_t event, http_response_t* response )
{
    switch( event )
    {
        case HTTP_CONNECTED: // Dont do anything
        break;

        case HTTP_DISCONNECTED: // Disconnect if you get this event
            wiced_rtos_set_semaphore(&requestSemaphore);
        break;

        case HTTP_DATA_RECEIVED: // Disconnect if you get this event
            wiced_rtos_set_semaphore(&requestSemaphore);
        break;

        default:
        break;
    }
}

 

Recommended Posts

No comment yet, add your voice below!


Add a Comment

Your email address will not be published. Required fields are marked *