141 lines
5.1 KiB
C
141 lines
5.1 KiB
C
|
|
||
|
/* Includes ------------------------------------------------------------------*/
|
||
|
#include <stdint.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "lwip/ip_addr.h"
|
||
|
#include "lwip/tcp.h"
|
||
|
#include "lwip/err.h"
|
||
|
#include "lwip/opt.h"
|
||
|
#include "lwip/sockets.h"
|
||
|
#include "stm32/ModbusS.h"
|
||
|
#include "esp_log.h"
|
||
|
// #include "log.h"
|
||
|
|
||
|
#define LOG_TAG "[mb_tcp_sr]: "
|
||
|
/* Private typedef -----------------------------------------------------------*/
|
||
|
/* Private define ------------------------------------------------------------*/
|
||
|
/* Private macro -------------------------------------------------------------*/
|
||
|
/* Private variables ---------------------------------------------------------*/
|
||
|
/* Private function prototypes -----------------------------------------------*/
|
||
|
// static err_t ModBusSlave_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
|
||
|
// static err_t ModBusSlave_accept(void *arg, struct tcp_pcb *pcb, err_t err);
|
||
|
// static void ModBusSlave_conn_err(void *arg, err_t err);
|
||
|
// static err_t ModBusSlave_poll(void *arg, struct tcp_pcb *pcb);
|
||
|
/* Private functions ---------------------------------------------------------*/
|
||
|
/**
|
||
|
* @brief Called when a data is received on the telnet connection
|
||
|
* @param arg the user argument
|
||
|
* @param pcb the tcp_pcb that has received the data
|
||
|
* @param p the packet buffer
|
||
|
* @param err the error value linked with the received data
|
||
|
* @retval error value
|
||
|
*/
|
||
|
int ModBusTcpMonitor;
|
||
|
static err_t ModBusSlave_recv(void *arg, struct tcp_pcb *newpcb, struct pbuf *p, err_t err) {
|
||
|
/* We perform here any necessary processing on the pbuf */
|
||
|
if (p != NULL) {
|
||
|
uint8_t *txbuf;
|
||
|
uint8_t *rxbuf;
|
||
|
int txlen, rxlen;
|
||
|
/* We call this function to tell the LwIp that we have processed the data */
|
||
|
/* This lets the stack advertise a larger window, so more data can be received*/
|
||
|
tcp_recved(newpcb, p->tot_len);
|
||
|
rxbuf = (uint8_t *)p->payload;
|
||
|
rxlen = p->len;
|
||
|
if (rxlen < 6) {
|
||
|
pbuf_free(p);
|
||
|
return tcp_close(newpcb);
|
||
|
}
|
||
|
txbuf = (uint8_t *)mem_malloc(1024 + 16);
|
||
|
if (txbuf == NULL) {
|
||
|
return tcp_close(newpcb);
|
||
|
}
|
||
|
ModBusTcpMonitor = 0;
|
||
|
txlen = ModbusSlaveProcess(&txbuf[6], &rxbuf[6], (rxlen - 6), 0); //以前有 2023年4月24日14:39:11
|
||
|
// log_printf(LINFO, LOG_TAG "[%s] ModbusSlaveProcess (ret=%d)", __FUNCTION__, txlen);
|
||
|
if (txlen > 0) {
|
||
|
int i;
|
||
|
for (i = 0; i < 4; i++) {
|
||
|
txbuf[i] = rxbuf[i];
|
||
|
}
|
||
|
txbuf[4] = (uint8_t)(txlen >> 8);
|
||
|
txbuf[5] = (uint8_t)(txlen & 0xff);
|
||
|
tcp_write(newpcb, txbuf, txlen + 6, 1);
|
||
|
ModBusTcpMonitor = 0;
|
||
|
}
|
||
|
mem_free(txbuf);
|
||
|
/* End of processing, we free the pbuf */
|
||
|
pbuf_free(p);
|
||
|
} else if (err == ERR_OK) {
|
||
|
/* When the pbuf is NULL and the err is ERR_OK, the remote end is closing the connection. */
|
||
|
/* We free the allocated memory and we close the connection */
|
||
|
// log_printf(LWARN, LOG_TAG "remote end is closing the connection\n");
|
||
|
tcp_err(newpcb, NULL);
|
||
|
tcp_recv(newpcb, NULL);
|
||
|
tcp_poll(newpcb, NULL, 120); // 60 second timeout
|
||
|
// return tcp_close(newpcb);
|
||
|
err_t err_p = tcp_close(newpcb);
|
||
|
if (ERR_OK != err_p) {
|
||
|
// log_printf(LERROR, LOG_TAG "close error. err:%d\n", err_p);
|
||
|
}
|
||
|
return err_p;
|
||
|
}
|
||
|
return ERR_OK;
|
||
|
}
|
||
|
/**
|
||
|
* @brief This function is called when an error occurs on the connection
|
||
|
* @param arg
|
||
|
* @parm err
|
||
|
* @retval None
|
||
|
*/
|
||
|
static void ModBusSlave_conn_err(void *arg, err_t err) {
|
||
|
// log_printf(LERROR, LOG_TAG "connection error, err:%d\n", err);
|
||
|
}
|
||
|
static err_t ModBusSlave_poll(void *arg, struct tcp_pcb *newpcb) {
|
||
|
// if (newpcb) {
|
||
|
// // log_printf(LERROR, LOG_TAG "close pcb\n");
|
||
|
// tcp_close(newpcb);
|
||
|
// newpcb = NULL;
|
||
|
// }
|
||
|
ESP_LOGI(LOG_TAG, "HELLO!");
|
||
|
return ERR_OK;
|
||
|
}
|
||
|
/**
|
||
|
* @brief This function when the Telnet connection is established
|
||
|
* @param arg user supplied argument
|
||
|
* @param pcb the tcp_pcb which accepted the connection
|
||
|
* @param err error value
|
||
|
* @retval ERR_OK
|
||
|
*/
|
||
|
static err_t ModBusSlave_accept(void *arg, struct tcp_pcb *pcb, err_t err) {
|
||
|
/* Tell LwIP to associate this structure with this connection. */
|
||
|
// tcp_arg(pcb, mem_calloc(sizeof(struct name), 1));
|
||
|
/* Configure LwIP to use our call back functions. */
|
||
|
tcp_err(pcb, ModBusSlave_conn_err);
|
||
|
tcp_recv(pcb, ModBusSlave_recv);
|
||
|
tcp_poll(pcb, ModBusSlave_poll, 1); // 60 second timeout
|
||
|
/* Send out the first message */
|
||
|
// tcp_write(pcb, GREETING, strlen(GREETING), 1);
|
||
|
return ERR_OK;
|
||
|
}
|
||
|
/**
|
||
|
* @brief Initialize the hello application
|
||
|
* @param None
|
||
|
* @retval None
|
||
|
*/
|
||
|
void ModBusTCPSlave_init(void) {
|
||
|
struct tcp_pcb *pcb;
|
||
|
/* Create a new TCP control block */
|
||
|
pcb = tcp_new();
|
||
|
/* Assign to the new pcb a local IP address and a port number */
|
||
|
/* Using IP_ADDR_ANY allow the pcb to be used by any local interface */
|
||
|
tcp_bind(pcb, IP_ADDR_ANY, 502);
|
||
|
/* Set the connection to the LISTEN state */
|
||
|
pcb = tcp_listen(pcb);
|
||
|
/* Specify the function to be called when a connection is established */
|
||
|
tcp_accept(pcb, ModBusSlave_accept);
|
||
|
// LSAPI_Log_Debug("ModBus Tcp server listen port:%d\n", 502);
|
||
|
}
|
||
|
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/
|