diff --git a/node1.c b/node1.c index d98a911..f7b77db 100644 --- a/node1.c +++ b/node1.c @@ -1,23 +1,23 @@ #include "bme280.h" +#include "pico/cyw43_arch.h" #include "pico/stdlib.h" #include "pms5003.h" -#include "pico/cyw43_arch.h" #include "tcp_client.h" #include #include #include +#include #include #include #include #include #include #include -#include // 5 sec loop is for testing -#define LOOP_INTERVAL_MS 5000 +// #define LOOP_INTERVAL_MS 5000 // #define LOOP_INTERVAL_MS 10000 -// #define LOOP_INTERVAL_MS 30000 +#define LOOP_INTERVAL_MS 30000 /** * Balcony Weather Station Node 1 @@ -41,22 +41,23 @@ void comms_led_blink() { gpio_put(16, comms_led_state); } void comms_led_update() { - if (time_reached(comms_led_off_time)) { - comms_led_state = false; - gpio_put(16, comms_led_state); - } + if (time_reached(comms_led_off_time)) { + comms_led_state = false; + gpio_put(16, comms_led_state); + } } // Callback to reset the Pico after 24 hours static bool cb_24h(__unused struct repeating_timer *t) { - printf("Restarting Pico after 24 hours...\n"); - watchdog_enable(1, 1); // 1 ms timeout, reset on next loop - while (1) { tight_loop_contents(); } // Wait for reset - return false; // Not reached + printf("Restarting Pico after 24 hours...\n"); + watchdog_enable(1, 1); // 1 ms timeout, reset on next loop + while (1) { + tight_loop_contents(); + } // Wait for reset + return false; // Not reached } static tcp_client_config tcp_config; -static bool wifi_connected = false; static pms5003_config pms_config; static pms5003_reading current_pms5003_reading; @@ -67,22 +68,23 @@ static bme280_reading current_bem280_reading; // Initialize WiFi connection bool wifi_init(void) { - if (cyw43_arch_init()) { - printf("Failed to initialize CYW43\n"); - return false; - } + printf("Initializing WiFi...\n"); + if (cyw43_arch_init()) { + printf("Failed to initialize CYW43\n"); + return false; + } - cyw43_arch_enable_sta_mode(); - printf("Connecting to WiFi '%s'...\n", WIFI_SSID); + cyw43_arch_enable_sta_mode(); + printf("Connecting to WiFi '%s'...\n", WIFI_SSID); - if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, - CYW43_AUTH_WPA2_AES_PSK, 30000)) { - printf("Failed to connect to WiFi\n"); - return false; - } + if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, + CYW43_AUTH_WPA2_AES_PSK, 60000)) { + printf("Failed to connect to WiFi\n"); + return false; + } - printf("WiFi connected successfully\n"); - return true; + printf("WiFi connected successfully\n"); + return true; } /** @@ -92,13 +94,10 @@ static bool cb_30(__unused struct repeating_timer *t) { comms_led_blink(); printf("cb_30: %d\n", readings_index); - - // Read BME280 printf("Making BME280 Reading\n"); current_bem280_reading = bme280_read(&bem_config); - if (readings_index == 2) { printf("Warming up PMSS5003\n"); pms5003_warmup(&pms_config); @@ -112,10 +111,6 @@ static bool cb_30(__unused struct repeating_timer *t) { if (readings_index == 6) { printf("Finished reading PMSS5003\n"); current_pms5003_reading = pms5003_finish_reading(&pms_config); - // TODO: send data to backend server if WiFi is connected - // printf("PM1: %.2f\n", current_pms5003_reading.pm1); - // printf("PM2.5: %.2f\n", current_pms5003_reading.pm2_5); - // printf("PM10: %.2f\n", current_pms5003_reading.pm10); } readings_index++; @@ -123,44 +118,35 @@ static bool cb_30(__unused struct repeating_timer *t) { readings_index = 0; } - if (!wifi_connected) { - printf("WiFi not connected, skipping send\n"); - return true; - } - char msg[256]; - snprintf(msg, sizeof(msg), - "M001,%.2f,%.2f,%2f\n", - current_bem280_reading.temperature, - current_bem280_reading.pressure, - current_bem280_reading.humidity); + snprintf(msg, sizeof(msg), "M001,%.2f,%.2f,%2f\n", + current_bem280_reading.temperature, current_bem280_reading.pressure, + current_bem280_reading.humidity); printf("Sending temperature, pressure, and humidity to backend server...\n"); printf("MSG: %s", msg); bool success = tcp_client_send_message(&tcp_config, msg); if (success) { - printf("✓ Data sent successfully\n"); - comms_led_blink(); + printf("✓ Data sent successfully\n"); + comms_led_blink(); } else { - printf("✗ Failed to send data\n"); - return false; + printf("✗ Failed to send data\n"); + return false; } // send PM readings if (readings_index == 6) { - snprintf(msg, sizeof(msg), - "M02,%.2f,%.2f,%2f\n", - current_pms5003_reading.pm1, - current_pms5003_reading.pm2_5, - current_pms5003_reading.pm10); + snprintf(msg, sizeof(msg), "M02,%.2f,%.2f,%2f\n", + current_pms5003_reading.pm1, current_pms5003_reading.pm2_5, + current_pms5003_reading.pm10); printf("Sending particulate matter readings to backend server...\n"); printf("MSG: %s", msg); bool success = tcp_client_send_message(&tcp_config, msg); if (success) { - printf("✓ Data sent successfully\n"); - comms_led_blink(); + printf("✓ Data sent successfully\n"); + comms_led_blink(); } else { - printf("✗ Failed to send data\n"); - return false; + printf("✗ Failed to send data\n"); + return false; } } @@ -170,34 +156,25 @@ static bool cb_30(__unused struct repeating_timer *t) { int main() { stdio_init_all(); watchdog_enable(60000, 1); - sleep_ms(2000); // Give time for USB serial + sleep_ms(2000); // Give time for USB serial // Initialize communication LED comms_led_init(); // Initialize WiFi - printf("Initializing WiFi...\n"); if (!wifi_init()) { - printf("WiFi initialization failed!\n"); - panic("WiFi initialization failed!"); - } else { - wifi_connected = true; - // Initialize TCP client - if (!tcp_client_init(&tcp_config, BACKEND_SERVER_IP, - BACKEND_SERVER_PORT, 10000)) { - printf("TCP client initialization failed\n"); - panic("TCP client initialization failed!"); - wifi_connected = false; - } else { - printf("TCP client ready: %s:%d\n", BACKEND_SERVER_IP, BACKEND_SERVER_PORT); - } + panic("WiFi initialization failed!"); + } + if (!tcp_client_init(&tcp_config, BACKEND_SERVER_IP, BACKEND_SERVER_PORT, + 20000)) { + panic("TCP client initialization failed!"); } // Setup BME280 bme280_init(&bem_config, i2c1, 14, 15); // Setup PMS5003 - // pms5003_init(&pms_config, uart1, 20, 21, 18, 19); + pms5003_init(&pms_config, uart1, 20, 21, 18, 19); struct repeating_timer timer_30; add_repeating_timer_ms(LOOP_INTERVAL_MS, cb_30, NULL, &timer_30); diff --git a/tcp_client.c b/tcp_client.c index dcb629c..5e3ea1b 100644 --- a/tcp_client.c +++ b/tcp_client.c @@ -4,247 +4,251 @@ */ #include "tcp_client.h" -#include -#include -#include -#include "pico/stdlib.h" -#include "pico/cyw43_arch.h" #include "lwip/pbuf.h" #include "lwip/tcp.h" +#include "pico/cyw43_arch.h" +#include "pico/stdlib.h" +#include "pico/time.h" +#include +#include +#include #define DEBUG_printf printf #define MAX_RETRY_COUNT 3 typedef struct { - struct tcp_pcb *tcp_pcb; - ip_addr_t remote_addr; - uint16_t remote_port; - const char *message; - int message_len; - int sent_len; - bool complete; - bool success; - bool connected; - uint32_t timeout_ms; - absolute_time_t timeout_time; + struct tcp_pcb *tcp_pcb; + ip_addr_t remote_addr; + uint16_t remote_port; + const char *message; + int message_len; + int sent_len; + bool complete; + bool success; + bool connected; + uint32_t timeout_ms; + absolute_time_t timeout_time; } tcp_client_state_t; static err_t tcp_client_close(tcp_client_state_t *state) { - err_t err = ERR_OK; - if (state->tcp_pcb != NULL) { - tcp_arg(state->tcp_pcb, NULL); - tcp_poll(state->tcp_pcb, NULL, 0); - tcp_sent(state->tcp_pcb, NULL); - tcp_recv(state->tcp_pcb, NULL); - tcp_err(state->tcp_pcb, NULL); - err = tcp_close(state->tcp_pcb); - if (err != ERR_OK) { - DEBUG_printf("tcp_client: close failed %d, calling abort\n", err); - tcp_abort(state->tcp_pcb); - err = ERR_ABRT; - } - state->tcp_pcb = NULL; + err_t err = ERR_OK; + if (state->tcp_pcb != NULL) { + tcp_arg(state->tcp_pcb, NULL); + tcp_poll(state->tcp_pcb, NULL, 0); + tcp_sent(state->tcp_pcb, NULL); + tcp_recv(state->tcp_pcb, NULL); + tcp_err(state->tcp_pcb, NULL); + err = tcp_close(state->tcp_pcb); + if (err != ERR_OK) { + DEBUG_printf("tcp_client: close failed %d, calling abort\n", err); + tcp_abort(state->tcp_pcb); + err = ERR_ABRT; } - return err; + state->tcp_pcb = NULL; + } + return err; } static err_t tcp_client_result(tcp_client_state_t *state, int status) { - if (status == 0) { - DEBUG_printf("tcp_client: send success\n"); - state->success = true; - } else { - DEBUG_printf("tcp_client: send failed %d\n", status); - state->success = false; - } - state->complete = true; - return tcp_client_close(state); + if (status == 0) { + DEBUG_printf("tcp_client: send success\n"); + state->success = true; + } else { + DEBUG_printf("tcp_client: send failed %d\n", status); + state->success = false; + } + state->complete = true; + return tcp_client_close(state); } static err_t tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) { - tcp_client_state_t *state = (tcp_client_state_t*)arg; - DEBUG_printf("tcp_client: sent %u bytes\n", len); - state->sent_len += len; + tcp_client_state_t *state = (tcp_client_state_t *)arg; + DEBUG_printf("tcp_client: sent %u bytes\n", len); + state->sent_len += len; - if (state->sent_len >= state->message_len) { - DEBUG_printf("tcp_client: message sent completely\n"); - return tcp_client_result(state, 0); - } + if (state->sent_len >= state->message_len) { + DEBUG_printf("tcp_client: message sent completely\n"); + return tcp_client_result(state, 0); + } - return ERR_OK; + return ERR_OK; } static err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err) { - tcp_client_state_t *state = (tcp_client_state_t*)arg; - if (err != ERR_OK) { - DEBUG_printf("tcp_client: connect failed %d\n", err); - return tcp_client_result(state, err); - } + tcp_client_state_t *state = (tcp_client_state_t *)arg; + if (err != ERR_OK) { + DEBUG_printf("tcp_client: connect failed %d\n", err); + return tcp_client_result(state, err); + } - state->connected = true; - DEBUG_printf("tcp_client: connected, sending message\n"); + state->connected = true; + DEBUG_printf("tcp_client: connected, sending message\n"); - // Send the message - cyw43_arch_lwip_begin(); - err_t write_err = tcp_write(tpcb, state->message, state->message_len, TCP_WRITE_FLAG_COPY); - if (write_err != ERR_OK) { - DEBUG_printf("tcp_client: failed to write data %d\n", write_err); - cyw43_arch_lwip_end(); - return tcp_client_result(state, -1); - } - - // Flush the data - err_t output_err = tcp_output(tpcb); + // Send the message + cyw43_arch_lwip_begin(); + err_t write_err = + tcp_write(tpcb, state->message, state->message_len, TCP_WRITE_FLAG_COPY); + if (write_err != ERR_OK) { + DEBUG_printf("tcp_client: failed to write data %d\n", write_err); cyw43_arch_lwip_end(); + return tcp_client_result(state, -1); + } - if (output_err != ERR_OK) { - DEBUG_printf("tcp_client: failed to output data %d\n", output_err); - return tcp_client_result(state, -1); - } + // Flush the data + err_t output_err = tcp_output(tpcb); + cyw43_arch_lwip_end(); - return ERR_OK; + if (output_err != ERR_OK) { + DEBUG_printf("tcp_client: failed to output data %d\n", output_err); + return tcp_client_result(state, -1); + } + + return ERR_OK; } static err_t tcp_client_poll(void *arg, struct tcp_pcb *tpcb) { - tcp_client_state_t *state = (tcp_client_state_t*)arg; - DEBUG_printf("tcp_client: poll timeout\n"); - return tcp_client_result(state, -1); + tcp_client_state_t *state = (tcp_client_state_t *)arg; + DEBUG_printf("tcp_client: poll timeout\n"); + return tcp_client_result(state, -1); } static void tcp_client_err(void *arg, err_t err) { - tcp_client_state_t *state = (tcp_client_state_t*)arg; - if (err != ERR_ABRT) { - DEBUG_printf("tcp_client: error %d\n", err); - state->success = false; - state->complete = true; - } + tcp_client_state_t *state = (tcp_client_state_t *)arg; + if (err != ERR_ABRT) { + DEBUG_printf("tcp_client: error %d\n", err); + state->success = false; + state->complete = true; + } } -static err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { - tcp_client_state_t *state = (tcp_client_state_t*)arg; +static err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, + err_t err) { + tcp_client_state_t *state = (tcp_client_state_t *)arg; - if (!p) { - DEBUG_printf("tcp_client: connection closed by server\n"); - return tcp_client_result(state, 0); - } + if (!p) { + DEBUG_printf("tcp_client: connection closed by server\n"); + return tcp_client_result(state, 0); + } - cyw43_arch_lwip_check(); + cyw43_arch_lwip_check(); - if (p->tot_len > 0) { - DEBUG_printf("tcp_client: received %d bytes (ignoring)\n", p->tot_len); - tcp_recved(tpcb, p->tot_len); - } - pbuf_free(p); + if (p->tot_len > 0) { + DEBUG_printf("tcp_client: received %d bytes (ignoring)\n", p->tot_len); + tcp_recved(tpcb, p->tot_len); + } + pbuf_free(p); - return ERR_OK; + return ERR_OK; } static bool tcp_client_open(tcp_client_state_t *state) { - DEBUG_printf("tcp_client: connecting to %s port %u\n", - ip4addr_ntoa(&state->remote_addr), state->remote_port); + DEBUG_printf("tcp_client: connecting to %s port %u\n", + ip4addr_ntoa(&state->remote_addr), state->remote_port); - state->tcp_pcb = tcp_new_ip_type(IP_GET_TYPE(&state->remote_addr)); - if (!state->tcp_pcb) { - DEBUG_printf("tcp_client: failed to create pcb\n"); - return false; - } + state->tcp_pcb = tcp_new_ip_type(IP_GET_TYPE(&state->remote_addr)); + if (!state->tcp_pcb) { + DEBUG_printf("tcp_client: failed to create pcb\n"); + return false; + } - tcp_arg(state->tcp_pcb, state); - tcp_poll(state->tcp_pcb, tcp_client_poll, 10); - tcp_sent(state->tcp_pcb, tcp_client_sent); - tcp_recv(state->tcp_pcb, tcp_client_recv); - tcp_err(state->tcp_pcb, tcp_client_err); + tcp_arg(state->tcp_pcb, state); + tcp_poll(state->tcp_pcb, tcp_client_poll, 10); + tcp_sent(state->tcp_pcb, tcp_client_sent); + tcp_recv(state->tcp_pcb, tcp_client_recv); + tcp_err(state->tcp_pcb, tcp_client_err); - state->sent_len = 0; - state->timeout_time = make_timeout_time_ms(state->timeout_ms); + state->sent_len = 0; + state->timeout_time = make_timeout_time_ms(state->timeout_ms); - cyw43_arch_lwip_begin(); - err_t err = tcp_connect(state->tcp_pcb, &state->remote_addr, - state->remote_port, tcp_client_connected); - cyw43_arch_lwip_end(); + cyw43_arch_lwip_begin(); + err_t err = tcp_connect(state->tcp_pcb, &state->remote_addr, + state->remote_port, tcp_client_connected); + cyw43_arch_lwip_end(); - if (err != ERR_OK) { - DEBUG_printf("tcp_client: tcp_connect failed %d\n", err); - return false; - } + if (err != ERR_OK) { + DEBUG_printf("tcp_client: tcp_connect failed %d\n", err); + return false; + } - return true; + return true; } bool tcp_client_init(tcp_client_config *config, const char *server_ip, uint16_t server_port, uint32_t timeout_ms) { - if (!config || !server_ip) { - return false; - } + if (!config || !server_ip) { + return false; + } - strncpy(config->server_ip, server_ip, sizeof(config->server_ip) - 1); - config->server_ip[sizeof(config->server_ip) - 1] = '\0'; - config->server_port = server_port; - config->timeout_ms = timeout_ms; - config->initialized = true; - config->internal_state = NULL; + strncpy(config->server_ip, server_ip, sizeof(config->server_ip) - 1); + config->server_ip[sizeof(config->server_ip) - 1] = '\0'; + config->server_port = server_port; + config->timeout_ms = timeout_ms; + config->initialized = true; + config->internal_state = NULL; - DEBUG_printf("tcp_client: initialized for %s:%u\n", config->server_ip, config->server_port); - return true; + DEBUG_printf("tcp_client: initialized for %s:%u\n", config->server_ip, + config->server_port); + return true; } bool tcp_client_send_message(tcp_client_config *config, const char *message) { - if (!config || !config->initialized || !message) { - DEBUG_printf("tcp_client: invalid config or message\n"); - return false; - } + if (!config || !config->initialized || !message) { + DEBUG_printf("tcp_client: invalid config or message\n"); + return false; + } - tcp_client_state_t *state = calloc(1, sizeof(tcp_client_state_t)); - if (!state) { - DEBUG_printf("tcp_client: failed to allocate state\n"); - return false; - } + tcp_client_state_t *state = calloc(1, sizeof(tcp_client_state_t)); + if (!state) { + DEBUG_printf("tcp_client: failed to allocate state\n"); + return false; + } - // Convert IP address - if (!ip4addr_aton(config->server_ip, &state->remote_addr)) { - DEBUG_printf("tcp_client: invalid IP address %s\n", config->server_ip); - free(state); - return false; - } - - state->remote_port = config->server_port; - state->message = message; - state->message_len = strlen(message); - state->timeout_ms = config->timeout_ms; - state->complete = false; - state->success = false; - state->connected = false; - - DEBUG_printf("tcp_client: sending message (%d bytes): %s\n", - state->message_len, message); - - if (!tcp_client_open(state)) { - DEBUG_printf("tcp_client: failed to open connection\n"); - free(state); - return false; - } - - // Wait for completion or timeout - while (!state->complete) { - if (time_reached(state->timeout_time)) { - DEBUG_printf("tcp_client: operation timed out\n"); - tcp_client_close(state); - state->complete = true; - state->success = false; - break; - } - cyw43_arch_poll(); - cyw43_arch_wait_for_work_until(make_timeout_time_ms(100)); - } - - bool success = state->success; + // Convert IP address + if (!ip4addr_aton(config->server_ip, &state->remote_addr)) { + DEBUG_printf("tcp_client: invalid IP address %s\n", config->server_ip); free(state); + return false; + } - return success; + state->remote_port = config->server_port; + state->message = message; + state->message_len = strlen(message); + state->timeout_ms = config->timeout_ms; + state->complete = false; + state->success = false; + state->connected = false; + + DEBUG_printf("tcp_client: sending message (%d bytes): %s\n", + state->message_len, message); + + if (!tcp_client_open(state)) { + DEBUG_printf("tcp_client: failed to open connection\n"); + free(state); + return false; + } + + // Wait for completion or timeout + while (!state->complete) { + cyw43_arch_poll(); + cyw43_arch_wait_for_work_until(make_timeout_time_ms(1000)); + if (time_reached(state->timeout_time)) { + DEBUG_printf("tcp_client: operation timed out\n"); + tcp_client_close(state); + state->complete = true; + state->success = false; + break; + } + } + + bool success = state->success; + free(state); + + return success; } void tcp_client_cleanup(tcp_client_config *config) { - if (config) { - config->initialized = false; - config->internal_state = NULL; - } + if (config) { + config->initialized = false; + config->internal_state = NULL; + } }