Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interrupt cloud connection when entering listening mode or powering off the device via setup button #1260

Merged
merged 1 commit into from May 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions system/inc/system_task.h
Expand Up @@ -90,6 +90,13 @@ uint8_t main_thread_current(void* reserved);

uint8_t application_thread_invoke(void (*callback)(void* data), void* data, void* reserved);

/**
* Cancels current network connection attempt and aborts cloud connection. This function can be
* called from an ISR and is used to unblock the system thread in order to perform some other
* operation immediately.
*/
void cancel_connection();

#ifdef __cplusplus
}
#endif
Expand Down
32 changes: 22 additions & 10 deletions system/src/main.cpp
Expand Up @@ -221,22 +221,30 @@ void system_display_rssi() {
ledCounter.start(bars);
}

void system_handle_button_click()
void system_power_off() {
LED_SIGNAL_START(POWER_OFF, CRITICAL);
SYSTEM_POWEROFF = 1;
cancel_connection(); // Unblock the system thread
}

void system_handle_button_clicks(bool isIsr)
{
const uint8_t clicks = button_final_clicks;
button_final_clicks = 0;
switch (clicks) {
case 1: // Single click
switch (button_final_clicks) {
case 1: { // Single click
if (isIsr) {
return; // The event will be processed in the system loop
}
system_display_rssi();
break;
case 2: // Double click
LED_SIGNAL_START(POWER_OFF, CRITICAL); // TODO: Start signal in a separate function
SYSTEM_POWEROFF = 1; // ...along with setting of this flag
network.connect_cancel(true);
}
case 2: { // Double click
system_power_off();
break;
}
default:
break;
}
button_final_clicks = 0;
}

#endif // #if Wiring_SetupButtonUX
Expand All @@ -249,6 +257,10 @@ void reset_button_click()
if (clicks > 0) {
system_notify_event(button_final_click, clicks);
button_final_clicks = clicks;
#if Wiring_SetupButtonUX
// Certain numbers of clicks can be processed directly in ISR
system_handle_button_clicks(HAL_IsISR());
#endif
}
}

Expand Down Expand Up @@ -444,7 +456,7 @@ extern "C" void HAL_SysTick_Handler(void)
// determine if the button press needs to change the state (and hasn't done so already))
else if(!network.listening() && HAL_Core_Mode_Button_Pressed(3000) && !wasListeningOnButtonPress)
{
network.connect_cancel(true);
cancel_connection(); // Unblock the system thread
// fire the button event to the user, then enter listening mode (so no more button notifications are sent)
// there's a race condition here - the HAL_notify_button_state function should
// be thread safe, but currently isn't.
Expand Down
24 changes: 16 additions & 8 deletions system/src/system_cloud_internal.cpp
Expand Up @@ -304,6 +304,7 @@ void encode_endpoint(sockaddr_t& tSocketAddr, const IPAddress& ip_addr, const ui
tSocketAddr.sa_data[5] = ip_addr[3];
}

volatile bool cloud_socket_aborted = false;

#if HAL_PLATFORM_CLOUD_UDP
struct Endpoint
Expand Down Expand Up @@ -331,9 +332,9 @@ SessionConnection cloud_endpoint;

int Spark_Send_UDP(const unsigned char* buf, uint32_t buflen, void* reserved)
{
if (SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed())
if (SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed() || cloud_socket_aborted)
{
DEBUG("SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || isSocketClosed()");
DEBUG("SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed() || cloud_socket_aborted");
//break from any blocking loop
return -1;
}
Expand All @@ -343,10 +344,10 @@ int Spark_Send_UDP(const unsigned char* buf, uint32_t buflen, void* reserved)

int Spark_Receive_UDP(unsigned char *buf, uint32_t buflen, void* reserved)
{
if (SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed())
if (SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed() || cloud_socket_aborted)
{
//break from any blocking loop
DEBUG("SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || isSocketClosed()");
DEBUG("SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed() || cloud_socket_aborted");
return -1;
}

Expand Down Expand Up @@ -387,9 +388,9 @@ int Spark_Receive_UDP(unsigned char *buf, uint32_t buflen, void* reserved)
// Returns number of bytes sent or -1 if an error occurred
int Spark_Send(const unsigned char *buf, uint32_t buflen, void* reserved)
{
if (SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed())
if (SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed() || cloud_socket_aborted)
{
DEBUG("SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || isSocketClosed()");
DEBUG("SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed() || cloud_socket_aborted");
//break from any blocking loop
return -1;
}
Expand All @@ -402,10 +403,10 @@ int Spark_Send(const unsigned char *buf, uint32_t buflen, void* reserved)
// Returns number of bytes received or -1 if an error occurred
int Spark_Receive(unsigned char *buf, uint32_t buflen, void* reserved)
{
if (SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed())
if (SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed() || cloud_socket_aborted)
{
//break from any blocking loop
DEBUG("SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || isSocketClosed()");
DEBUG("SPARK_WLAN_RESET || SPARK_WLAN_SLEEP || spark_cloud_socket_closed() || cloud_socket_aborted");
return -1;
}

Expand Down Expand Up @@ -667,6 +668,7 @@ const int CLAIM_CODE_SIZE = 63;

int Spark_Handshake(bool presence_announce)
{
cloud_socket_aborted = false; // Clear cancellation flag for socket operations
LOG(INFO,"Starting handshake: presense_announce=%d", presence_announce);
int err = spark_protocol_handshake(sp);
if (!err)
Expand Down Expand Up @@ -1369,3 +1371,9 @@ void Spark_Wake(void)
spark_protocol_command(sp, ProtocolCommands::WAKE);
#endif
}

void Spark_Abort() {
#ifndef SPARK_NO_CLOUD
cloud_socket_aborted = true;
#endif
}
1 change: 1 addition & 0 deletions system/src/system_cloud_internal.h
Expand Up @@ -41,6 +41,7 @@ void Spark_SetTime(unsigned long dateTime);
void Spark_Process_Events();
void Spark_Sleep();
void Spark_Wake();
void Spark_Abort();

void system_set_time(time_t time, unsigned param, void* reserved);

Expand Down
12 changes: 10 additions & 2 deletions system/src/system_task.cpp
Expand Up @@ -408,7 +408,7 @@ static void process_isr_task_queue()
}

#if Wiring_SetupButtonUX
extern void system_handle_button_click();
extern void system_handle_button_clicks(bool isIsr);
#endif

void Spark_Idle_Events(bool force_events/*=false*/)
Expand All @@ -423,7 +423,7 @@ void Spark_Idle_Events(bool force_events/*=false*/)
if (!SYSTEM_POWEROFF) {

#if Wiring_SetupButtonUX
system_handle_button_click();
system_handle_button_clicks(false /* isIsr */);
#endif
manage_serial_flasher();

Expand Down Expand Up @@ -581,3 +581,11 @@ uint8_t application_thread_invoke(void (*callback)(void* data), void* data, void
callback(data);
return 0;
}

void cancel_connection()
{
// Cancel current network connection attempt
network.connect_cancel(true);
// Abort cloud connection
Spark_Abort();
}