init tcp_test
This commit is contained in:
parent
1a25129495
commit
7e6125066e
4 changed files with 312 additions and 50 deletions
|
|
@ -44,7 +44,7 @@ endif()
|
||||||
|
|
||||||
|
|
||||||
# the executable
|
# the executable
|
||||||
add_executable(node1 node1.c bme280.c pms5003.c mqtt_client.c)
|
add_executable(node1 node1.c bme280.c pms5003.c)
|
||||||
pico_set_program_version(node1 "0.1")
|
pico_set_program_version(node1 "0.1")
|
||||||
pico_set_program_name(node1 "node_one")
|
pico_set_program_name(node1 "node_one")
|
||||||
|
|
||||||
|
|
@ -67,20 +67,25 @@ target_compile_definitions(node1 PRIVATE
|
||||||
# create map/bin/hex file etc.
|
# create map/bin/hex file etc.
|
||||||
pico_add_extra_outputs( node1 )
|
pico_add_extra_outputs( node1 )
|
||||||
|
|
||||||
# == WIFI SCAN ==
|
# == TCP TEST ==
|
||||||
|
|
||||||
add_executable(wifi_scan wifi_scan.c)
|
add_executable(tcp_test tcp.c)
|
||||||
target_include_directories(wifi_scan PRIVATE
|
target_include_directories(tcp_test PRIVATE
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts
|
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(wifi_scan
|
target_link_libraries(tcp_test
|
||||||
pico_cyw43_arch_lwip_threadsafe_background
|
pico_cyw43_arch_lwip_threadsafe_background
|
||||||
pico_stdlib
|
pico_stdlib
|
||||||
)
|
)
|
||||||
|
|
||||||
pico_add_extra_outputs(wifi_scan)
|
target_compile_definitions(tcp_test PRIVATE
|
||||||
|
WIFI_SSID=\"${WIFI_SSID}\"
|
||||||
|
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
|
||||||
|
)
|
||||||
|
|
||||||
|
pico_add_extra_outputs(tcp_test)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,51 +2,60 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
HOST = "0.0.0.0"
|
|
||||||
PORT = "8080"
|
|
||||||
TYPE = "tcp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
listen, err := net.Listen(TYPE, HOST+":"+PORT)
|
addr := "192.168.1.153:8080"
|
||||||
println("Listening on", HOST+":"+PORT)
|
fmt.Printf("Starting TCP server on port %s\n", addr)
|
||||||
|
//Address to bind to
|
||||||
|
//Resolve address
|
||||||
|
addr_, err := net.ResolveTCPAddr("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
fmt.Printf("Error resolving address: %s", err.Error())
|
||||||
os.Exit(1)
|
return
|
||||||
}
|
}
|
||||||
// close listener
|
//Listen for incoming connections
|
||||||
defer listen.Close()
|
listener, err := net.ListenTCP("tcp", addr_)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error starting server: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer listener.Close()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
conn, err := listen.Accept()
|
//Accept incoming connection
|
||||||
|
conn, err := listener.AcceptTCP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
fmt.Printf("Error accepting connection: %s", err.Error())
|
||||||
os.Exit(1)
|
continue
|
||||||
}
|
}
|
||||||
go handleRequest(conn)
|
go handleConnection(conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleRequest(conn net.Conn) {
|
func handleConnection(conn *net.TCPConn) {
|
||||||
// incoming request
|
defer conn.Close()
|
||||||
|
fmt.Printf("New connection from %s\n", conn.RemoteAddr().String())
|
||||||
|
|
||||||
buffer := make([]byte, 1024)
|
buffer := make([]byte, 1024)
|
||||||
_, err := conn.Read(buffer)
|
for {
|
||||||
if err != nil {
|
//Read up to 1024 bytes
|
||||||
log.Fatal(err)
|
n, err := conn.Read(buffer)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error reading from connection: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("Received message: %s\n", string(buffer[:n]))
|
||||||
|
//Echo message back
|
||||||
|
// _, err = conn.Write(buffer[:n])
|
||||||
|
_, err = conn.Write([]byte("1"))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error writing to connection: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// write data to response
|
|
||||||
time := time.Now().Format(time.ANSIC)
|
|
||||||
fmt.Printf("Message recived: %v. Received time: %v", string(buffer[:]), time)
|
|
||||||
conn.Write([]byte("1"))
|
|
||||||
// conn.Write([]byte(responseStr))
|
|
||||||
|
|
||||||
// close conn
|
|
||||||
conn.Close()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
node1.c
17
node1.c
|
|
@ -1,7 +1,6 @@
|
||||||
#include "bme280.h"
|
#include "bme280.h"
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "pms5003.h"
|
#include "pms5003.h"
|
||||||
#include "mqtt_client.h"
|
|
||||||
#include <hardware/gpio.h>
|
#include <hardware/gpio.h>
|
||||||
#include <hardware/i2c.h>
|
#include <hardware/i2c.h>
|
||||||
#include <hardware/uart.h>
|
#include <hardware/uart.h>
|
||||||
|
|
@ -56,8 +55,6 @@ static bool cb_24h(__unused struct repeating_timer *t) {
|
||||||
return false; // Not reached
|
return false; // Not reached
|
||||||
}
|
}
|
||||||
|
|
||||||
static mqtt_client_config mqtt_config;
|
|
||||||
|
|
||||||
static pms5003_config pms_config;
|
static pms5003_config pms_config;
|
||||||
static pms5003_reading current_pms5003_reading;
|
static pms5003_reading current_pms5003_reading;
|
||||||
|
|
||||||
|
|
@ -101,12 +98,13 @@ static bool cb_30(__unused struct repeating_timer *t) {
|
||||||
printf("PM2.5: %.2f\n", current_pms5003_reading.pm2_5);
|
printf("PM2.5: %.2f\n", current_pms5003_reading.pm2_5);
|
||||||
printf("PM10: %.2f\n", current_pms5003_reading.pm10);
|
printf("PM10: %.2f\n", current_pms5003_reading.pm10);
|
||||||
// char msg[100];
|
// char msg[100];
|
||||||
char msg[200];
|
// char msg[200];
|
||||||
snprintf(msg, sizeof(msg), "{\"temp\": %.2f, \"pressure\": %.2f, \"humidity\": %.2f, \"pm1\": %.2f, \"pm2_5\": %.2f, \"pm10\": %.2f}\n",
|
// snprintf(msg, sizeof(msg), "{\"temp\": %.2f, \"pressure\": %.2f, \"humidity\": %.2f, \"pm1\": %.2f, \"pm2_5\": %.2f, \"pm10\": %.2f}\n",
|
||||||
current_bem280_reading.temperature, current_bem280_reading.pressure, current_bem280_reading.humidity,
|
// current_bem280_reading.temperature, current_bem280_reading.pressure, current_bem280_reading.humidity,
|
||||||
current_pms5003_reading.pm1, current_pms5003_reading.pm2_5, current_pms5003_reading.pm10);
|
// current_pms5003_reading.pm1, current_pms5003_reading.pm2_5, current_pms5003_reading.pm10);
|
||||||
printf("Sending data to home assistant...\n");
|
printf("Sending data to home assistant...\n");
|
||||||
mqtt_client_pub_message(&mqtt_config, msg);
|
// printf
|
||||||
|
// mqtt_client_pub_message(&mqtt_config, msg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,7 +139,6 @@ int main() {
|
||||||
// Initialize communication LED
|
// Initialize communication LED
|
||||||
comms_led_init();
|
comms_led_init();
|
||||||
|
|
||||||
mqtt_client_init(&mqtt_config, "homeassistant/sensor/bws/node1/state", "bws-node1");
|
|
||||||
|
|
||||||
// Setup BME280
|
// Setup BME280
|
||||||
bme280_init(&bem_config, i2c1, 14, 15);
|
bme280_init(&bem_config, i2c1, 14, 15);
|
||||||
|
|
@ -155,9 +152,7 @@ int main() {
|
||||||
add_repeating_timer_ms(86400000, cb_24h, NULL, &timer_24h);
|
add_repeating_timer_ms(86400000, cb_24h, NULL, &timer_24h);
|
||||||
while (true) {
|
while (true) {
|
||||||
comms_led_update();
|
comms_led_update();
|
||||||
sleep_us(100);
|
|
||||||
tight_loop_contents();
|
tight_loop_contents();
|
||||||
mqtt_client_do_network_stuff(&mqtt_config);
|
|
||||||
watchdog_update();
|
watchdog_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
253
tcp.c
Normal file
253
tcp.c
Normal file
|
|
@ -0,0 +1,253 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "pico/cyw43_arch.h"
|
||||||
|
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/tcp.h"
|
||||||
|
|
||||||
|
#define TEST_TCP_SERVER_IP "192.168.1.153"
|
||||||
|
|
||||||
|
#define TCP_PORT 8080
|
||||||
|
#define BUF_SIZE 2048
|
||||||
|
|
||||||
|
#define TEST_ITERATIONS 10
|
||||||
|
#define POLL_TIME_S 5
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void dump_bytes(const uint8_t *bptr, uint32_t len) {
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
printf("dump_bytes %d", len);
|
||||||
|
for (i = 0; i < len;) {
|
||||||
|
if ((i & 0x0f) == 0) {
|
||||||
|
printf("\n");
|
||||||
|
} else if ((i & 0x07) == 0) {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
printf("%02x ", bptr[i++]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#define DUMP_BYTES dump_bytes
|
||||||
|
#else
|
||||||
|
#define DUMP_BYTES(A,B)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct TCP_CLIENT_T_ {
|
||||||
|
struct tcp_pcb *tcp_pcb;
|
||||||
|
ip_addr_t remote_addr;
|
||||||
|
uint8_t buffer[BUF_SIZE];
|
||||||
|
int buffer_len;
|
||||||
|
int sent_len;
|
||||||
|
bool complete;
|
||||||
|
int run_count;
|
||||||
|
bool connected;
|
||||||
|
} TCP_CLIENT_T;
|
||||||
|
|
||||||
|
static err_t tcp_client_close(void *arg) {
|
||||||
|
TCP_CLIENT_T *state = (TCP_CLIENT_T*)arg;
|
||||||
|
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) {
|
||||||
|
printf("close failed %d, calling abort\n", err);
|
||||||
|
tcp_abort(state->tcp_pcb);
|
||||||
|
err = ERR_ABRT;
|
||||||
|
}
|
||||||
|
state->tcp_pcb = NULL;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called with results of operation
|
||||||
|
static err_t tcp_result(void *arg, int status) {
|
||||||
|
TCP_CLIENT_T *state = (TCP_CLIENT_T*)arg;
|
||||||
|
if (status == 0) {
|
||||||
|
printf("test success\n");
|
||||||
|
} else {
|
||||||
|
printf("test failed %d\n", status);
|
||||||
|
}
|
||||||
|
state->complete = true;
|
||||||
|
return tcp_client_close(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static err_t tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) {
|
||||||
|
TCP_CLIENT_T *state = (TCP_CLIENT_T*)arg;
|
||||||
|
printf("tcp_client_sent %u\n", len);
|
||||||
|
state->sent_len += len;
|
||||||
|
|
||||||
|
if (state->sent_len >= BUF_SIZE) {
|
||||||
|
|
||||||
|
state->run_count++;
|
||||||
|
if (state->run_count >= TEST_ITERATIONS) {
|
||||||
|
tcp_result(arg, 0);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should receive a new buffer from the server
|
||||||
|
state->buffer_len = 0;
|
||||||
|
state->sent_len = 0;
|
||||||
|
printf("Waiting for buffer from server\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err) {
|
||||||
|
TCP_CLIENT_T *state = (TCP_CLIENT_T*)arg;
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
printf("connect failed %d\n", err);
|
||||||
|
return tcp_result(arg, err);
|
||||||
|
}
|
||||||
|
state->connected = true;
|
||||||
|
printf("Waiting for buffer from server\n");
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static err_t tcp_client_poll(void *arg, struct tcp_pcb *tpcb) {
|
||||||
|
printf("tcp_client_poll\n");
|
||||||
|
return tcp_result(arg, -1); // no response is an error?
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcp_client_err(void *arg, err_t err) {
|
||||||
|
if (err != ERR_ABRT) {
|
||||||
|
printf("tcp_client_err %d\n", err);
|
||||||
|
tcp_result(arg, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
|
||||||
|
TCP_CLIENT_T *state = (TCP_CLIENT_T*)arg;
|
||||||
|
if (!p) {
|
||||||
|
return tcp_result(arg, -1);
|
||||||
|
}
|
||||||
|
// this method is callback from lwIP, so cyw43_arch_lwip_begin is not required, however you
|
||||||
|
// can use this method to cause an assertion in debug mode, if this method is called when
|
||||||
|
// cyw43_arch_lwip_begin IS needed
|
||||||
|
cyw43_arch_lwip_check();
|
||||||
|
if (p->tot_len > 0) {
|
||||||
|
printf("recv %d err %d\n", p->tot_len, err);
|
||||||
|
for (struct pbuf *q = p; q != NULL; q = q->next) {
|
||||||
|
DUMP_BYTES(q->payload, q->len);
|
||||||
|
}
|
||||||
|
// Receive the buffer
|
||||||
|
const uint16_t buffer_left = BUF_SIZE - state->buffer_len;
|
||||||
|
state->buffer_len += pbuf_copy_partial(p, state->buffer + state->buffer_len,
|
||||||
|
p->tot_len > buffer_left ? buffer_left : p->tot_len, 0);
|
||||||
|
tcp_recved(tpcb, p->tot_len);
|
||||||
|
}
|
||||||
|
pbuf_free(p);
|
||||||
|
|
||||||
|
// If we have received the whole buffer, send it back to the server
|
||||||
|
if (state->buffer_len == BUF_SIZE) {
|
||||||
|
printf("Writing %d bytes to server\n", state->buffer_len);
|
||||||
|
err_t err = tcp_write(tpcb, state->buffer, state->buffer_len, TCP_WRITE_FLAG_COPY);
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
printf("Failed to write data %d\n", err);
|
||||||
|
return tcp_result(arg, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tcp_client_open(void *arg) {
|
||||||
|
TCP_CLIENT_T *state = (TCP_CLIENT_T*)arg;
|
||||||
|
printf("Connecting to %s port %u\n", ip4addr_ntoa(&state->remote_addr), TCP_PORT);
|
||||||
|
state->tcp_pcb = tcp_new_ip_type(IP_GET_TYPE(&state->remote_addr));
|
||||||
|
if (!state->tcp_pcb) {
|
||||||
|
printf("failed to create pcb\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_arg(state->tcp_pcb, state);
|
||||||
|
tcp_poll(state->tcp_pcb, tcp_client_poll, POLL_TIME_S * 2);
|
||||||
|
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->buffer_len = 0;
|
||||||
|
|
||||||
|
// cyw43_arch_lwip_begin/end should be used around calls into lwIP to ensure correct locking.
|
||||||
|
// You can omit them if you are in a callback from lwIP. Note that when using pico_cyw_arch_poll
|
||||||
|
// these calls are a no-op and can be omitted, but it is a good practice to use them in
|
||||||
|
// case you switch the cyw43_arch type later.
|
||||||
|
cyw43_arch_lwip_begin();
|
||||||
|
err_t err = tcp_connect(state->tcp_pcb, &state->remote_addr, TCP_PORT, tcp_client_connected);
|
||||||
|
cyw43_arch_lwip_end();
|
||||||
|
|
||||||
|
return err == ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform initialisation
|
||||||
|
static TCP_CLIENT_T* tcp_client_init(void) {
|
||||||
|
TCP_CLIENT_T *state = calloc(1, sizeof(TCP_CLIENT_T));
|
||||||
|
if (!state) {
|
||||||
|
printf("failed to allocate state\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ip4addr_aton(TEST_TCP_SERVER_IP, &state->remote_addr);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_tcp_client_test(void) {
|
||||||
|
TCP_CLIENT_T *state = tcp_client_init();
|
||||||
|
if (!state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!tcp_client_open(state)) {
|
||||||
|
tcp_result(state, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while(!state->complete) {
|
||||||
|
// the following #ifdef is only here so this same example can be used in multiple modes;
|
||||||
|
// you do not need it in your code
|
||||||
|
#if PICO_CYW43_ARCH_POLL
|
||||||
|
// if you are using pico_cyw43_arch_poll, then you must poll periodically from your
|
||||||
|
// main loop (not from a timer) to check for Wi-Fi driver or lwIP work that needs to be done.
|
||||||
|
cyw43_arch_poll();
|
||||||
|
// you can poll as often as you like, however if you have nothing else to do you can
|
||||||
|
// choose to sleep until either a specified time, or cyw43_arch_poll() has work to do:
|
||||||
|
cyw43_arch_wait_for_work_until(make_timeout_time_ms(1000));
|
||||||
|
#else
|
||||||
|
// if you are not using pico_cyw43_arch_poll, then WiFI driver and lwIP work
|
||||||
|
// is done via interrupt in the background. This sleep is just an example of some (blocking)
|
||||||
|
// work you might be doing.
|
||||||
|
sleep_ms(1000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
free(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
if (cyw43_arch_init()) {
|
||||||
|
printf("failed to initialise\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
cyw43_arch_enable_sta_mode();
|
||||||
|
|
||||||
|
printf("Connecting to Wi-Fi...\n");
|
||||||
|
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
|
||||||
|
printf("failed to connect.\n");
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
printf("Connected.\n");
|
||||||
|
}
|
||||||
|
run_tcp_client_test();
|
||||||
|
cyw43_arch_deinit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue