I try to make a solution sending Homematic data over WLan.
After struggeling around with configurations and serveral examples,
this code do basicly this function.
Code: Select all
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "lwip/sockets.h"
#define PORT_NUMBER 23
#define WIFI_PW CONFIG_WIFI_PASSWORD
#define WIFI_SSID CONFIG_WIFI_SSID
#define EX_UART_NUM UART_NUM_1
#define BUF_SIZE 128
#define TXD_IO (GPIO_NUM_10)
#define RXD_IO (GPIO_NUM_9)
static struct sockaddr_in serverAddress;
static struct sockaddr_in clientAddress;
static char tag[] = "socket_server";
static int sock = -1;
static int clientSock = 0;
static uint8_t init_socket(void)
{
int ret = 0;
u32_t optlen = sizeof(ret);
socklen_t clientAddressLength = sizeof(clientAddress);
clientSock = accept(sock, (struct sockaddr *)&clientAddress, &clientAddressLength);
if (clientSock < 1) {
ESP_LOGE(tag, "NOT accept: %d %s", clientSock, strerror(errno));
return 0;
}
getsockopt(clientSock, SOL_SOCKET, SO_ERROR, &ret, &optlen);
ESP_LOGI(tag, "accept: %d %s ", clientSock, strerror(ret));
return 1;
}
static void uart_tx_Task(void *pvParameters)
{
static const char *TX_TAG = "TX_TASK";
esp_log_level_set(TX_TAG, ESP_LOG_INFO);
static const char *RX_TAG = "RX_TASK";
esp_log_level_set(RX_TAG, ESP_LOG_INFO);
uint8_t* txdata = (uint8_t*)malloc(10*BUF_SIZE);
uint8_t* rxdata = (uint8_t*)malloc(10*BUF_SIZE);
ssize_t socketRead;
ssize_t socketWrite;
int uartWrite;
int uartRead;
int ret = 0;
u32_t optlen = sizeof(ret);
uint8_t stateRead = 1;
uint8_t stateWrite = 0;
uint8_t client_connected = (uint8_t)init_socket();
while (1) {
if(! client_connected)
{
if(init_socket())
{
stateRead = 1;
stateWrite = 0;
client_connected = 1;
}
}
else if(client_connected && stateRead) {
socketRead = recv(clientSock, txdata, 10*BUF_SIZE, 0);
if (socketRead <= 0) {
getsockopt(clientSock, SOL_SOCKET, SO_ERROR, &ret, &optlen);
ESP_LOGE(tag, "Socket Closed: %d %s", clientSock, strerror(ret));
close(clientSock);
stateRead = 0;
stateWrite = 0;
client_connected = 0;
}
else {
uartWrite = uart_write_bytes(EX_UART_NUM, (const char*) txdata, socketRead);
ESP_LOGI(TX_TAG, "uart data Sent: %s, bytes: %d,", txdata,uartWrite);
// ESP_LOG_BUFFER_HEX(TX_TAG,txdata,uartWrite );
stateRead = 0;
stateWrite = 1;
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
else if(client_connected && stateWrite) {
uartRead = uart_read_bytes(EX_UART_NUM, rxdata, 10*BUF_SIZE, 100 / portTICK_PERIOD_MS);
if(uartRead > 0) {
ESP_LOGI(RX_TAG, "Uart Data receive:d %s, bytes: %d", rxdata,uartRead);
socketWrite = send(clientSock, rxdata, uartRead, 0);
if (socketWrite <= 0) {
getsockopt(clientSock, SOL_SOCKET, SO_ERROR, &ret, &optlen);
ESP_LOGE(tag, "Socket Closed: %d %s", clientSock, strerror(ret));
close(clientSock);
stateRead = 0;
stateWrite = 0;
client_connected = 0;
}
else {
ESP_LOGI(RX_TAG, "Data sent Socket: %s, bytes: %d, socket %d", rxdata, socketWrite,clientSock);
// ESP_LOG_BUFFER_HEX(RX_TAG,rxdata,socketWrite );
stateRead = 1;
stateWrite = 0;
}
}
}
}
vTaskDelete(NULL);
}
static void tcp_sock_init(void)
{
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
ESP_LOGE(tag, "socket: %d %s", sock, strerror(errno));
exit(1);
}
ESP_LOGI(tag, "socket created");
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(PORT_NUMBER);
int rc = bind(sock, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
if (rc < 0) {
ESP_LOGE(tag, "bind: %d %s", rc, strerror(errno));
exit(1);
}
ESP_LOGI(tag, "socket bound");
rc = listen(sock,1);
if (rc < 0) {
ESP_LOGE(tag, "listen: %d %s", rc, strerror(errno));
exit(1);
}
ESP_LOGI(tag, "socket listen");
xTaskCreate(uart_tx_Task, "uart_tx_Task", 4000, NULL, 5, NULL);
}
esp_err_t event_handler(void *ctx, system_event_t *event)
{
switch (event->event_id){
case SYSTEM_EVENT_STA_GOT_IP:
printf("Our IP address is " IPSTR "\n", IP2STR(&event->event_info.got_ip.ip_info.ip));
printf("Starting TCP Socket Init...\n");
tcp_sock_init();
break;
case SYSTEM_EVENT_WIFI_READY:
printf("Wifi ready\n");
break;
case SYSTEM_EVENT_STA_START:
printf("Station started\n");
break;
case SYSTEM_EVENT_STA_CONNECTED:
printf("Station connected\n");
break;
default:
printf("Other Event\n");
break;
}
return ESP_OK;
}
static void wifi_init(void)
{
ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
wifi_config_t sta_config = {
.sta = {
.ssid = WIFI_SSID,
.password = WIFI_PW,
.bssid_set = false
}
};
ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config) );
ESP_ERROR_CHECK( esp_wifi_start() );
ESP_ERROR_CHECK( esp_wifi_connect() );
}
static void uart_init(void)
{
/* Configure parameters of an UART driver,
* communication pins and install the driver */
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(EX_UART_NUM, &uart_config);
uart_set_pin(EX_UART_NUM, TXD_IO, RXD_IO, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, NULL, 0);
}
void app_main(void)
{
nvs_flash_init();
tcpip_adapter_init();
wifi_init();
uart_init();
gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT);
int level = 0;
while (true) {
gpio_set_level(GPIO_NUM_2, level);
level = !level;
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
after seconds or some minutes on CPU0 which leads to a hanging system or reboot.
I think I need something like a flow control but in which manner?
Events? Interrupt? SW flowcontrol? What is the common way in this case?
Maybe with a little example?
regards,
linuxpaul