Skip to content

Commit

Permalink
feat(common_examples): Add common examples aplicable for all phys
Browse files Browse the repository at this point in the history
  • Loading branch information
bogdankolendovskyy committed Apr 15, 2024
1 parent a631cfe commit e668a8c
Show file tree
Hide file tree
Showing 33 changed files with 388 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
strategy:
matrix:
idf_ver: ["latest"]
example: ["simple-ethernet"]
example: ["simple-ethernet", "iperf", "tcp_server"]
idf_target: ["esp32"]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
Expand All @@ -23,5 +23,5 @@ jobs:
run: |
. ${IDF_PATH}/export.sh
pip install idf-build-apps
cd $GITHUB_WORKSPACE/esp_eth_drivers/ethernet_init/examples/${{ matrix.example }}
cd $GITHUB_WORKSPACE/esp_eth_drivers/common_examples/${{ matrix.example }}
idf-build-apps build -p . --target ${{ matrix.idf_target }} --build-dir build_@t_@w --config 'sdkconfig.defaults.*='
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ GPATH
**/examples/**/sdkconfig.old
**/examples/**/build
**/examples/**/managed_components
common_examples/**/sdkconfig
common_examples/**/sdkconfig.old
common_examples/**/build
common_examples/**/managed_components

# Doc build artifacts
docs/_build/
Expand Down
8 changes: 8 additions & 0 deletions common_examples/iperf/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(iperf)
2 changes: 2 additions & 0 deletions common_examples/iperf/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRCS "iperf.c"
INCLUDE_DIRS ".")
7 changes: 7 additions & 0 deletions common_examples/iperf/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
menu "Iperf example-specific options"
config EXAMPLE_ACT_AS_DHCP_SERVER
bool "Act sa DHCP server"
default n
help
Set ESP32 to act as DHCP server instead of as a client.
endmenu
5 changes: 5 additions & 0 deletions common_examples/iperf/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dependencies:
espressif/ethernet_init:
override_path: '../../../ethernet_init/'
espressif/iperf-cmd: "^0.1.1"
espressif/iperf: "^0.1.1"
63 changes: 63 additions & 0 deletions common_examples/iperf/main/iperf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include "esp_netif.h"
#include "esp_eth.h"
#include "esp_event.h"
#include "esp_console.h"
#include "ethernet_init.h"
#include "iperf_cmd.h"
#include "sdkconfig.h"

static void my_event_connected_handler(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data)
{
esp_netif_dhcps_start(esp_netif);
}


void app_main(void)
{
uint8_t eth_port_cnt = 0;
esp_eth_handle_t *eth_handles;
esp_netif_init();
esp_event_loop_create_default();
ethernet_init_all(&eth_handles, &eth_port_cnt);

//esp_netif_config_t cfg;
#if CONFIG_EXAMPLE_ACT_AS_DHCP_SERVER
// Act as DHCP server
esp_netif_ip_info_t ip_info = {
.ip = {.addr = ESP_IP4TOADDR(192, 168, 1, 1)},
.netmask = {.addr = ESP_IP4TOADDR(255, 255, 255, 0)},
.gw = {.addr = ESP_IP4TOADDR(192, 168, 1, 255)}
};
const esp_netif_inherent_config_t eth_behav_cfg = {
.get_ip_event = IP_EVENT_ETH_GOT_IP,
.lost_ip_event = 0,
.flags = ESP_NETIF_DHCP_SERVER,
.ip_info = &ip_info,
.if_key = "ETH_DHCPS",
.if_desc = "eth",
.route_prio = 50
};
esp_netif_config_t cfg = { .base = &eth_behav_cfg, .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH };

esp_netif_t *eth_netif = esp_netif_new(&cfg);
esp_eth_handle_t eth_handle = eth_handles[0];
esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0]));

esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, my_event_connected_handler, eth_netif);
esp_netif_dhcpc_stop(eth_netif);
esp_netif_set_ip_info(eth_netif, &ip_info);
#else
// Act as DHCP client, usual behaviour
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&cfg);
esp_eth_handle_t eth_handle = eth_handles[0];
esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0]));
#endif
esp_eth_start(eth_handle);
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
esp_console_new_repl_uart(&uart_config, &repl_config, &repl);
app_register_iperf_commands();
esp_console_start_repl(repl);
}
1 change: 1 addition & 0 deletions common_examples/iperf/sdkconfig.defaults.client
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_EXAMPLE_ACT_AS_DHCP_SERVER=n
1 change: 1 addition & 0 deletions common_examples/iperf/sdkconfig.defaults.server
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_EXAMPLE_ACT_AS_DHCP_SERVER=y
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ dependencies:
ethernet_init:
version: '*'
# For local development use the local copy of the component
override_path: '../../../'
override_path: '../../../ethernet_init/'
8 changes: 8 additions & 0 deletions common_examples/tcp_client/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(tcp_client)
2 changes: 2 additions & 0 deletions common_examples/tcp_client/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRCS "tcp_client.c"
INCLUDE_DIRS ".")
7 changes: 7 additions & 0 deletions common_examples/tcp_client/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
dependencies:
idf:
version: '>=5.0'
ethernet_init:
version: '*'
# For local development use the local copy of the component
override_path: '../../../ethernet_init/'
75 changes: 75 additions & 0 deletions common_examples/tcp_client/main/tcp_client.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_netif.h"
#include "esp_eth.h"
#include "esp_event.h"
#include "esp_log.h"
#include "ethernet_init.h"
#include "lwip/sockets.h"

#define SOCKET_PORT 5000
#define SOCKET_MAX_LENGTH 128

static const char *TAG = "tcp_client";
static SemaphoreHandle_t xGotIpSemaphore;

/** Event handler for IP_EVENT_ETH_GOT_IP */
static void got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *data)
{
ip_event_got_ip_t *event = (ip_event_got_ip_t *) data;
const esp_netif_ip_info_t *ip_info = &event->ip_info;

ESP_LOGI(TAG, "Ethernet Got IP Address");
ESP_LOGI(TAG, "~~~~~~~~~~~");
ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip));
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
ESP_LOGI(TAG, "~~~~~~~~~~~");
xSemaphoreGive(xGotIpSemaphore);
}

void app_main(void)
{
// Create default event loop that running in background
ESP_ERROR_CHECK(esp_event_loop_create_default());
// Initialize semaphore
xGotIpSemaphore = xSemaphoreCreateBinary();
// Initialize Ethernet driver
uint8_t eth_port_cnt = 0;
esp_eth_handle_t *eth_handles;
ESP_ERROR_CHECK(ethernet_init_all(&eth_handles, &eth_port_cnt));
// Initialize TCP/IP network interface aka the esp-netif (should be called only once in application)
ESP_ERROR_CHECK(esp_netif_init());
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&cfg);
// Attach Ethernet driver to TCP/IP stack
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0])));
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
// Start Ethernet driver
esp_eth_start(eth_handles[0]);
// Wait until IP address is assigned to this device
xSemaphoreTake(xGotIpSemaphore, portMAX_DELAY);
int client_fd;
struct sockaddr_in server;
char rxbuffer[SOCKET_MAX_LENGTH] = {0};
char txbuffer[SOCKET_MAX_LENGTH] = {0};
client_fd = socket(AF_INET, SOCK_STREAM, 0);
server.sin_family = AF_INET;
server.sin_port = htons(SOCKET_PORT);
server.sin_addr.s_addr = inet_addr("192.168.1.0"); // To do: Find a way to get this ip and not hardcode it
connect(client_fd, (struct sockaddr *)&server, sizeof(struct sockaddr));
int transmission_cnt = 0;
while (1) {
snprintf(txbuffer, SOCKET_MAX_LENGTH, "Transmission #%d. Hello from ESP32 TCP client", ++transmission_cnt);
ESP_LOGI(TAG, "Transmitting: \"%s\"", txbuffer);
write(client_fd, txbuffer, SOCKET_MAX_LENGTH);
read(client_fd, rxbuffer, SOCKET_MAX_LENGTH);
ESP_LOGI(TAG, "Received \"%s\"", rxbuffer);
memset(txbuffer, 0, SOCKET_MAX_LENGTH);
memset(rxbuffer, 0, SOCKET_MAX_LENGTH);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
49 changes: 49 additions & 0 deletions common_examples/tcp_client/tcp_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env python3
import socket
import argparse
import logging
import signal

def port_type(astr, min=1, max=65535):
value = int(astr)
if min<= value <= max:
return value
else:
raise argparse.ArgumentTypeError('value not in range %s-%s'%(min,max))

parser = argparse.ArgumentParser(description='Serve TCP connection using berkley sockets and wait for connections', epilog='Part of the tcp_client example for esp_eth_drivers')
parser.add_argument('ip')
parser.add_argument('-p', '--port', type=port_type, default=5000, choices=range(1, 65535), metavar="PORT", help='Port to listen on')
parser.add_argument('-s', '--silent', action='store_true', help="Do not log incoming transmissions")
args = parser.parse_args()

# setup sigint handler
signal.signal(signal.SIGINT, lambda s, f : exit(0))

logger = logging.getLogger("tcp_server")
logging.basicConfig(format="%(name)s :: %(levelname)-8s :: %(message)s", level=logging.DEBUG)
if args.silent:
logger.setLevel(logging.INFO)
logger.info("Listening on %s:%d", args.ip, args.port)

# init server
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((args.ip, args.port))
# listen for incoming connections
sock.listen(1)

counter = 1
while True:
conn, address = sock.accept()
logger.debug("Accepted connection from %s:%d", address[0], address[1])
while True:
try:
data = conn.recv(128).decode()
except ConnectionAbortedError:
logger.info("Connection closed by client")
break
logger.debug("Received: \"%s\"", data)
msg = f"Transmission {counter}: Hello from Python"
logger.debug("Transmitting: \"%s\"", msg)
conn.sendall(str.encode(msg))
counter += 1
8 changes: 8 additions & 0 deletions common_examples/tcp_server/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(tcp_server)
2 changes: 2 additions & 0 deletions common_examples/tcp_server/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRCS "tcp_server.c"
INCLUDE_DIRS ".")
7 changes: 7 additions & 0 deletions common_examples/tcp_server/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
dependencies:
idf:
version: '>=5.0'
ethernet_init:
version: '*'
# For local development use the local copy of the component
override_path: '../../../ethernet_init/'
75 changes: 75 additions & 0 deletions common_examples/tcp_server/main/tcp_server.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_netif.h"
#include "esp_eth.h"
#include "esp_event.h"
#include "esp_log.h"
#include "ethernet_init.h"
#include "lwip/sockets.h"

#define SOCKET_PORT 5000
#define SOCKET_MAX_LENGTH 128
static const char *TAG = "tcp_server";

/** Event handler for IP_EVENT_ETH_GOT_IP */
static void got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *data)
{
ip_event_got_ip_t *event = (ip_event_got_ip_t *) data;
const esp_netif_ip_info_t *ip_info = &event->ip_info;

ESP_LOGI(TAG, "Ethernet Got IP Address");
ESP_LOGI(TAG, "~~~~~~~~~~~");
ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip));
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
ESP_LOGI(TAG, "~~~~~~~~~~~");
}

void app_main(void)
{
// Create default event loop that running in background
ESP_ERROR_CHECK(esp_event_loop_create_default());
// Initialize Ethernet driver
uint8_t eth_port_cnt = 0;
esp_eth_handle_t *eth_handles;
ESP_ERROR_CHECK(ethernet_init_all(&eth_handles, &eth_port_cnt));
// Initialize TCP/IP network interface aka the esp-netif (should be called only once in application)
ESP_ERROR_CHECK(esp_netif_init());
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&cfg);
// Attach Ethernet driver to TCP/IP stack
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0])));
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
// Start Ethernet driver
esp_eth_start(eth_handles[0]);
int server_fd, client_fd;
struct sockaddr_in server, client;
char rxbuffer[SOCKET_MAX_LENGTH] = {0};
char txbuffer[SOCKET_MAX_LENGTH] = {0};
server_fd = socket(AF_INET, SOCK_STREAM, 0);

server.sin_family = AF_INET;
server.sin_port = htons(SOCKET_PORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);

int opt_val = 1;
bind(server_fd, (struct sockaddr *) &server, sizeof(server));
listen(server_fd, 1);
int transmission_cnt = 0;
while (1) {
socklen_t client_len = sizeof(client);
client_fd = accept(server_fd, (struct sockaddr *) &client, &client_len);
while (1) {
int read = recv(client_fd, rxbuffer, SOCKET_MAX_LENGTH, 0);
if (!read) {
break; // done reading
}
ESP_LOGI(TAG, "Received \"%s\"", rxbuffer);
snprintf(txbuffer, SOCKET_MAX_LENGTH, "Transmission #%d. Hello from ESP32 TCP server", ++transmission_cnt);
send(client_fd, txbuffer, read, 0);
}
}
}
Loading

0 comments on commit e668a8c

Please sign in to comment.