Xively C library
Dependents: xively-jumpstart-demo
This is Xively C library, the code lives on GitHub.
See our example program and the tutorial, documentation can bee found here.
Diff: src/libxively/xively.c
- Revision:
- 0:53753690a8bf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libxively/xively.c Mon May 13 19:28:22 2013 +0000 @@ -0,0 +1,367 @@ +// Copyright (c) 2003-2013, LogMeIn, Inc. All rights reserved. +// This is part of Xively C library, it is under the BSD 3-Clause license. + +/** + * \file xively.c + * \brief Xively C library [see xively.h] + */ + +#include <string.h> +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +#include "xi_allocator.h" +#include "xively.h" +#include "http_transport.h" +#include "csv_data_layer.h" +#include "xi_macros.h" +#include "xi_debug.h" +#include "xi_helpers.h" +#include "xi_err.h" +#include "xi_globals.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Get instance of _communication layer_ + * + * \note Although the interface is of the _communication layer_ should + * stay the same, some implemantation may differ. + * + * \return Pointer to the communication layer interface + */ +const comm_layer_t* get_comm_layer( void ); + +#include "comm_layer.h" + +//----------------------------------------------------------------------- +// HELPER MACROS +//----------------------------------------------------------------------- + +#define XI_FUNCTION_VARIABLES connection_t* conn = 0;\ + const comm_layer_t* comm_layer = 0;\ + const transport_layer_t* transport_layer = 0;\ + const data_layer_t* data_layer = 0;\ + char buffer[ XI_HTTP_MAX_CONTENT_SIZE ];\ + const xi_response_t* response = 0;\ + int sent = 0;\ + int recv = 0; + +#define XI_FUNCTION_PROLOGUE XI_FUNCTION_VARIABLES\ + xi_debug_log_str( "Getting the comm layer...\n" );\ + comm_layer = get_comm_layer();\ + xi_debug_log_str( "Getting the transport layer...\n" );\ + transport_layer = get_http_transport_layer();\ + xi_debug_log_str( "Getting the data layer...\n");\ + data_layer = get_csv_data_layer();\ + +#define XI_FUNCTION_GET_RESPONSE if( data == 0 ) { goto err_handling; }\ + xi_debug_log_str( "Connecting to the endpoint...\n" );\ + conn = comm_layer->open_connection( XI_HOST, XI_PORT );\ + if( conn == 0 ) { goto err_handling; }\ + xi_debug_log_str( "Sending data:\n" );\ + xi_debug_log_data( data );\ + sent = comm_layer->send_data( conn, data, strlen( data ) );\ + if( sent == -1 ) { goto err_handling; }\ + xi_debug_log_str( "Sent: " );\ + xi_debug_log_int( ( int ) sent );\ + xi_debug_log_endl();\ + xi_debug_log_str( "Reading data...\n" );\ + recv = comm_layer->read_data( conn, buffer, XI_HTTP_MAX_CONTENT_SIZE );\ + if( recv == -1 ) { goto err_handling; }\ + xi_debug_log_str( "Received: " );\ + xi_debug_log_int( ( int ) recv );\ + xi_debug_log_endl();\ + xi_debug_log_str( "Response:\n" );\ + xi_debug_log_data( buffer );\ + xi_debug_log_endl();\ + response = transport_layer->decode_reply(\ + data_layer, buffer );\ + if( response == 0 ) { goto err_handling; }\ + +#define XI_FUNCTION_EPILOGUE xi_debug_log_str( "Closing connection...\n" );\ +err_handling:\ + if( conn )\ + {\ + comm_layer->close_connection( conn );\ + }\ + return response;\ + +//----------------------------------------------------------------------- +// HELPER FUNCTIONS +//----------------------------------------------------------------------- + +xi_datapoint_t* xi_set_value_i32( xi_datapoint_t* p, int32_t value ) +{ + // PRECONDITION + assert( p != 0 ); + + p->value.i32_value = value; + p->value_type = XI_VALUE_TYPE_I32; + + return p; +} + +xi_datapoint_t* xi_set_value_f32( xi_datapoint_t* p, float value ) +{ + // PRECONDITION + assert( p != 0 ); + + p->value.f32_value = value; + p->value_type = XI_VALUE_TYPE_F32; + + return p; +} + +xi_datapoint_t* xi_set_value_str( xi_datapoint_t* p, const char* value ) +{ + // PRECONDITION + assert( p != 0 ); + + int s = xi_str_copy_untiln( p->value.str_value + , XI_VALUE_STRING_MAX_SIZE, value, '\0' ); + + XI_CHECK_SIZE( s, XI_VALUE_STRING_MAX_SIZE, XI_DATAPOINT_VALUE_BUFFER_OVERFLOW ); + + p->value_type = XI_VALUE_TYPE_STR; + + return p; + +err_handling: + return 0; +} + +void xi_set_network_timeout( uint32_t timeout ) +{ + xi_globals.network_timeout = timeout; +} + +uint32_t xi_get_network_timeout( void ) +{ + return xi_globals.network_timeout; +} + +//----------------------------------------------------------------------- +// MAIN LIBRARY FUNCTIONS +//----------------------------------------------------------------------- + +xi_context_t* xi_create_context( + xi_protocol_t protocol, const char* api_key + , int32_t feed_id ) +{ + // allocate the structure to store new context + xi_context_t* ret = ( xi_context_t* ) xi_alloc( sizeof( xi_context_t ) ); + + XI_CHECK_MEMORY( ret ); + + // copy given numeric parameters as is + ret->protocol = protocol; + ret->feed_id = feed_id; + + // copy string parameters carefully + if( api_key ) + { + // duplicate the string + ret->api_key = xi_str_dup( api_key ); + + XI_CHECK_MEMORY( ret->api_key ); + } + else + { + ret->api_key = 0; + } + + return ret; + +err_handling: + if( ret ) + { + XI_SAFE_FREE( ret ); + } + + return 0; +} + +void xi_delete_context( xi_context_t* context ) +{ + if( context ) + { + XI_SAFE_FREE( context->api_key ); + } + XI_SAFE_FREE( context ); +} + +const xi_response_t* xi_feed_get( + xi_context_t* xi + , xi_feed_t* feed ) +{ + XI_FUNCTION_PROLOGUE + + const char* data = transport_layer->encode_get_feed( + data_layer + , xi->api_key + , feed ); + + if( data == 0 ) { goto err_handling; } + + XI_FUNCTION_GET_RESPONSE + + feed = data_layer->decode_feed( response->http.http_content, feed ); + if( feed == 0 ) { goto err_handling; } + + XI_FUNCTION_EPILOGUE +} + +const xi_response_t* xi_feed_update( + xi_context_t* xi + , const xi_feed_t* feed ) +{ + XI_FUNCTION_PROLOGUE + + const char* data = transport_layer->encode_update_feed( + data_layer + , xi->api_key + , feed ); + + if( data == 0 ) { goto err_handling; } + + XI_FUNCTION_GET_RESPONSE + + XI_FUNCTION_EPILOGUE +} + +const xi_response_t* xi_datastream_get( + xi_context_t* xi, int32_t feed_id + , const char * datastream_id, xi_datapoint_t* o ) +{ + XI_FUNCTION_PROLOGUE + + const char* data = transport_layer->encode_get_datastream( + data_layer + , xi->api_key + , feed_id + , datastream_id ); + + if( data == 0 ) { goto err_handling; } + + XI_FUNCTION_GET_RESPONSE + + o = data_layer->decode_datapoint( + response->http.http_content, o ); + + if( o == 0 ) { goto err_handling; } + + XI_FUNCTION_EPILOGUE +} + + +const xi_response_t* xi_datastream_create( + xi_context_t* xi, int32_t feed_id + , const char * datastream_id + , const xi_datapoint_value_t* value ) +{ + XI_FUNCTION_PROLOGUE + + const char* data = transport_layer->encode_create_datastream( + data_layer + , xi->api_key + , feed_id + , datastream_id + , value ); + + if( data == 0 ) { goto err_handling; } + + XI_FUNCTION_GET_RESPONSE + XI_FUNCTION_EPILOGUE +} + +const xi_response_t* xi_datastream_update( + xi_context_t* xi, int32_t feed_id + , const char * datastream_id + , const xi_datapoint_value_t* value ) +{ + XI_FUNCTION_PROLOGUE + + const char* data = transport_layer->encode_update_datastream( + data_layer + , xi->api_key + , feed_id + , datastream_id + , value ); + + + if( data == 0 ) { goto err_handling; } + + XI_FUNCTION_GET_RESPONSE + + + XI_FUNCTION_EPILOGUE +} +const xi_response_t* xi_datastream_delete( + xi_context_t* xi, int32_t feed_id + , const char * datastream_id ) +{ + XI_FUNCTION_PROLOGUE + + const char* data = transport_layer->encode_delete_datastream( + data_layer + , xi->api_key + , feed_id + , datastream_id ); + + if( data == 0 ) { goto err_handling; } + + XI_FUNCTION_GET_RESPONSE + + XI_FUNCTION_EPILOGUE +} + +const xi_response_t* xi_datapoint_delete( + const xi_context_t* xi, int feed_id + , const char * datastream_id + , const xi_datapoint_t* o ) +{ + XI_FUNCTION_PROLOGUE + + const char* data = transport_layer->encode_delete_datapoint( + data_layer + , xi->api_key + , feed_id + , datastream_id + , o ); + + if( data == 0 ) { goto err_handling; } + + XI_FUNCTION_GET_RESPONSE + XI_FUNCTION_EPILOGUE +} + +extern const xi_response_t* xi_datapoint_delete_range( + const xi_context_t* xi, int feed_id + , char * datastream_id + , const xi_timestamp_t* start + , const xi_timestamp_t* end ) +{ + XI_FUNCTION_PROLOGUE + + const char* data = transport_layer->encode_datapoint_delete_range( + data_layer + , xi->api_key + , feed_id + , datastream_id + , start + , end ); + + if( data == 0 ) { goto err_handling; } + + XI_FUNCTION_GET_RESPONSE + XI_FUNCTION_EPILOGUE +} + + +#ifdef __cplusplus +} +#endif