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¶ms=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;
}
}





































