network/tcp_client/main.c

/*******************************************************************************
* # License
* Copyright 2019 Silicon Laboratories Inc. www.silabs.com
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
/* Documentation for this app is available online.
* See https://docs.silabs.com/gecko-os/4/standard/latest/sdk/examples/network/tcp-client
*/
#include "gos.h"
#include "example_app_util.h"
#define BUTTON_DEBOUNCE_TIME_MS 50
#define BUTTON_CLICK_TIME_MS 500
#define BUTTON_PRESS_TIME_MS 1000
#define TCP_HOST "test.zentri.com"
#define TCP_PORT 50007
#define NETWORK_UP_PERIOD_MS 7000 // ms
#define ATTEMPT_CONNECT_PERIOD_MS 5000 // ms
#define TRANSMIT_PERIOD_MS 1000 // ms
#define APPLICATION_START_LINE "\r\nTCP Client example starting ..."
uint32_t packet_counter;
/*************************************************************************************************/
void gos_app_init(void)
{
gos_result_t result;
GOS_LOG(APPLICATION_START_LINE);
if(GOS_FAILED(result, initialize_hardware()))
{
GOS_LOG("Failed to initialize hardware");
return;
}
if (GOS_FAILED(result, gos_load_app_settings("settings.ini")))
{
GOS_LOG("Failed to load settings, err:%d", result);
return;
}
if (GOS_FAILED(result, example_app_util_network_up(GOS_INTERFACE_ANY, false, network_event_handler)))
{
}
}
/*************************************************************************************************/
static void network_event_handler(bool is_up)
{
if (is_up == true)
{
GOS_LOG("Network up");
gos_event_issue(tcp_attempt_connect_handler, NULL, 0);
}
else
{
GOS_LOG("Network down");
gos_event_issue(network_up_handler, NULL, 0);
}
}
/*************************************************************************************************/
static void network_up_handler(void *arg)
{
gos_result_t result;
GOS_LOG("Attempting to bring network up ...");
gos_event_unregister(network_up_handler, NULL);
{
GOS_LOG("Failed to bring up up, err:%d", result);
GOS_LOG("Trying again in %d seconds", NETWORK_UP_PERIOD_MS/1000);
gos_event_register_timed(network_up_handler, NULL, NETWORK_UP_PERIOD_MS, 0);
}
}
/*************************************************************************************************/
static void tcp_attempt_connect_handler(void *arg)
{
gos_result_t result;
gos_handle_t stream_handle;
{
network_event_handler(false);
return;
}
GOS_LOG("Attempting to connect to %s:%u", TCP_HOST, TCP_PORT);
if (GOS_FAILED(result, gos_tcp_connect(GOS_INTERFACE_DEFAULT, TCP_HOST, TCP_PORT, &stream_handle)))
{
GOS_LOG("Failed to connect. Trying again in %d seconds", ATTEMPT_CONNECT_PERIOD_MS/1000);
gos_event_register_timed(tcp_attempt_connect_handler, NULL, ATTEMPT_CONNECT_PERIOD_MS, 0);
return;
}
GOS_LOG("Connected. Stream handle: %d", stream_handle);
packet_counter = 0;
gos_tcp_register_client_event_handlers(stream_handle, tcp_disconnect_handler, tcp_receive_handler);
gos_event_register_periodic(tcp_transmit_handler, (void*)stream_handle, TRANSMIT_PERIOD_MS, GOS_EVENT_FLAGS1(RUN_NOW));
}
/*************************************************************************************************/
static void tcp_disconnect_handler(gos_handle_t handle)
{
GOS_LOG("Server disconnected, attempting to read any remaining data");
gos_event_unregister(tcp_transmit_handler, NULL);
tcp_receive_handler(handle);
GOS_LOG("Closing tcp handle: %d", handle);
GOS_LOG("Restarting connection timer");
gos_event_issue(tcp_attempt_connect_handler, NULL, 0);
}
/*************************************************************************************************/
static void tcp_receive_handler(gos_handle_t handle)
{
gos_result_t result;
gos_buffer_t buffer = {.size = 0};
if (GOS_FAILED(result, gos_tcp_poll(handle, &buffer.size, NULL)))
{
GOS_LOG("Failed to poll TCP stream, err:%d", result);
return;
}
else if (buffer.size == 0)
{
return;
}
if (GOS_FAILED(result, gos_tcp_read_with_buffer(handle, &buffer)))
{
GOS_LOG("Failed to read data, err:%d", result);
return;
}
gos_write_log((char*)buffer.data, buffer.size);
}
/*************************************************************************************************/
static void tcp_transmit_handler(void *arg)
{
gos_handle_t handle = (gos_handle_t)arg;
gos_result_t result;
char buffer[128];
uint32_t gpio_values;
gpio_values = gos_gpio_mask_get(UINT32_MAX);
const int len = sprintf(buffer, "%3u: Time:%s, GPIOs:%08X\r\n", (unsigned int)packet_counter, (const char*)&time_str, (unsigned int)gpio_values);
packet_counter++;
if (GOS_FAILED(result, gos_tcp_write(handle, buffer, len, false)))
{
GOS_LOG("Failed to transmit data, err:%d", result);
}
}
/*************************************************************************************************
* Initialize the buttons.
*/
static gos_result_t initialize_hardware(void)
{
gos_result_t result;
const gos_button_config_t config =
{
.active_level = PLATFORM_BUTTON_ACTIVE_STATE,
.debounce = BUTTON_DEBOUNCE_TIME_MS,
.click_time = BUTTON_CLICK_TIME_MS,
.press_time = BUTTON_PRESS_TIME_MS,
.event_handler.press = NULL,
.event_handler.click = NULL,
.event_handler.toggle = NULL,
.execution_context = GOS_BUTTON_CONTEXT_DEFAULT
};
GOS_LOG("Initializing button 1 ...");
if(GOS_FAILED(result, gos_button_init(PLATFORM_BUTTON1, &config, (void*)1)))
{
GOS_LOG("Failed to init PLATFORM_BUTTON1, err:%d", result);
return result;
}
GOS_LOG("Initializing button 2 ...");
if(GOS_FAILED(result, gos_button_init(PLATFORM_BUTTON2, &config, (void*)2)))
{
GOS_LOG("Failed to init PLATFORM_BUTTON2, err:%d", result);
return result;
}
return GOS_SUCCESS;
}