реклама на сайте
подробности

 
 
> lwIP Client
Александр П.
сообщение Feb 20 2014, 13:18
Сообщение #1





Группа: Участник
Сообщений: 14
Регистрация: 25-12-13
Пользователь №: 79 787



Добрый день.
Есть связка MCU + удаленный девайс. Связаны по Ethernet. Требуется периодически посылать на удаленный девайс сообщение и принимать от него ответ.
Использую lwIP стек. Ниже приведен работающий код. В конечном итоге callback функция ReturnPg возвращает ответ удаленного девайса. Вопрос. Как реализовать периодический опрос.
main.c
CODE
//==============================================================================
static void ReturnPg(u8_t num, hc_errormsg msg, char *data, u16_t len)
{
// data - ответ удаленного устройства
}
//==============================================================================
int main(void)
{
struct ip_addr ipaddr, netmask, gw;
struct netif NetIf, *netif;
#if LWIP_DHCP
u8_t dhcp_state = DHCP_INIT;
#endif
// Disable watchdog
WDT_Disable( WDT );
#if defined (ddram)
MMU_Initialize((uint32_t *)0x30C000);
CP15_EnableMMU();
CP15_EnableIcache();
CP15_EnableDcache();
#endif
// Initialize system timing
sys_init_timing();
// Initialize lwIP modules
lwip_init();
// Initialize net interface for lwIP
gmacif_setmac((u8_t*)gMacAddress);

IP4_ADDR(&gw, gGateWay[0], gGateWay[1], gGateWay[2], gGateWay[3]);
IP4_ADDR(&ipaddr, gIpAddress[0], gIpAddress[1], gIpAddress[2], gIpAddress[3]);
IP4_ADDR(&netmask, gNetMask[0], gNetMask[1], gNetMask[2], gNetMask[3]);

netif = netif_add(&NetIf, &gw, &netmask, &ipaddr, NULL, gmacif_init, ip_input);
netif_set_default(netif);
netif_set_up(netif);

char page[] ="get_param1";

hc_open(ipaddr, page, 0, &ReturnPg);

while(1)
{
// Run periodic tasks
timers_update();
// Run polling tasks
gmacif_poll(netif);

}
}


webclient.c
CODE
#include <board.h>
#include <liblwip.h>
#include "lwip/opt.h"
#include "lwip/tcp.h"

#include <stdlib.h>
#include <string.h>
#include "webclient.h"
//==============================================================================
// Close a PCB(connection)
//==============================================================================
static void hc_clearpcb(struct tcp_pcb *pcb)
{
if(pcb != NULL)
{
// Close the TCP connection
tcp_close(pcb);
}
}
//==============================================================================
// Function that lwip calls for handling recv'd data
//==============================================================================
static err_t hc_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct hc_state *state = arg;
char * page = NULL;
struct pbuf * temp_p;
hc_errormsg errormsg = GEN_ERROR;
int i;

if((err == ERR_OK) && (p != NULL))
{
tcp_recved(pcb, p->tot_len);

// Add payload (p) to state
temp_p = p;
while(temp_p != NULL)
{
state->RecvData = realloc(state->RecvData, temp_p->len + state->Len + 1);

// CHECK 'OUT OF MEM'
if(state->RecvData == NULL)
{
// OUT OF MEMORY
(*state->ReturnPage)(state->Num, OUT_MEM, NULL, 0);
return(ERR_OK);
}

strncpy(state->RecvData + state->Len, temp_p->payload, temp_p->len);
state->RecvData[temp_p->len + state->Len] = '\0';
state->Len += temp_p->len;

temp_p = temp_p->next;
}

// Removing payloads

while(p != NULL)
{
temp_p = p->next;
pbuf_free(p);
p = temp_p;
}

}

// NULL packet == CONNECTION IS CLOSED(by remote host)
else if((err == ERR_OK) && (p == NULL))
{
// Simple code for checking 200 OK
for(i=0; i < state->Len; i++)
{
if(errormsg == GEN_ERROR)
{
// Check for 200 OK
if((*(state->RecvData+i) == '2') && (*(state->RecvData+ ++i) == '0') && (*(state->RecvData+ ++i) == '0')) errormsg = OK;
if(*(state->RecvData+i) == '\n') errormsg = NOT_FOUND;
}
else
{
// Remove headers
if((*(state->RecvData+i) == '\r') && (*(state->RecvData+ ++i) == '\n') && (*(state->RecvData+ ++i) == '\r') && (*(state->RecvData + ++i) == '\n'))
{
i++;
page = malloc(strlen(state->RecvData+i));
strcpy(page, state->RecvData+i);
break;
}
}
}

if(errormsg == OK)
{
// Put recv data to ---> p->ReturnPage
(*state->ReturnPage)(state->Num, OK, page, state->Len);
}
else
{
// 200 OK not found Return NOT_FOUND (WARNING: NOT_FOUND COULD ALSO BE 5xx SERVER ERROR, ...)
(*state->ReturnPage)(state->Num, errormsg, NULL, 0);
}

// Clear the PCB
hc_clearpcb(pcb);

// free the memory containing state
free(state->RecvData);
free(state);
}

return(ERR_OK);
}
//==============================================================================
// Function that lwip calls when there is an error
//==============================================================================
static void hc_error(void *arg, err_t err)
{
struct hc_state *state = arg;
// pcb already deallocated

// Call return function
// TO-DO: Check err_t err for out_mem, ...
(*state->ReturnPage)(state->Num, GEN_ERROR, NULL, 0);

free(state->RecvData);
//free(state->PostVars);
free(state->Page);
free(state);
}
//==============================================================================
// Function that lwip calls when the connection is idle
// Here we can kill connections that have stayed idle for too long
//==============================================================================
static err_t hc_poll(void *arg, struct tcp_pcb *pcb)
{
struct hc_state *state = arg;

state->ConnectionTimeout++;
if(state->ConnectionTimeout > 20)
{
// Close the connection
tcp_abort(pcb);

// Give err msg to callback function
// Call return function
(*state->ReturnPage)(state->Num, TIMEOUT, NULL, 0);
}

return(ERR_OK);
}
//==============================================================================
// lwip calls this function when the remote host has successfully received data (ack)
//==============================================================================
static err_t hc_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct hc_state *state = arg;

// Reset connection timeout
state->ConnectionTimeout = 0;

return(ERR_OK);
}
//==============================================================================
// lwip calls this function when the connection is established
//==============================================================================
char *str1;
char str2[100];
static err_t hc_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct hc_state *state = arg;
char * headers;

// error?
if(err != ERR_OK)
{
hc_clearpcb(pcb);

// Call return function
(*state->ReturnPage)(state->Num, GEN_ERROR, NULL, 0);

// Free wc state
free(state->RecvData);
free(state);

return(ERR_OK);
}

// Define Headers

// GET headers (without page)(+ \0) = 19
headers = malloc(19 + strlen(state->Page));
//usprintf(headers,"GET /%s HTTP/1.0\r\n\r\n", state->Page);
sprintf(headers,"GET /%s HTTP/1.0\r\n\r\n", state->Page);

// Check if we are nut running out of memory
if(headers == NULL)
{
hc_clearpcb(pcb);

// Call return function
(*state->ReturnPage)(state->Num, OUT_MEM, NULL, 0);

// Free wc state
free(state->RecvData);
free(state);

return(ERR_OK);
}

// Setup the TCP receive function
tcp_recv(pcb, hc_recv);

// Setup the TCP error function
tcp_err(pcb, hc_error);

// Setup the TCP polling function/interval //TCP_POLL IS NOT CORRECT DEFINED @ DOC!!!
tcp_poll(pcb, hc_poll, 10);

// Setup the TCP sent callback function
tcp_sent(pcb, hc_sent);

// Send data
strcpy(str2,headers);
tcp_write(pcb, headers, strlen(headers), 1);
tcp_output(pcb);

// remove headers
free(headers);
//free(state->PostVars); // postvars are send, so we don't need them anymore
free(state->Page); // page is requested, so we don't need it anymore

return(ERR_OK);
}
//==============================================================================
// Public function for request a webpage (REMOTEIP, ...
//==============================================================================
int hc_open(struct ip_addr remoteIP, char *Page, char *PostVars, void (* returnpage)(u8_t, hc_errormsg, char *, u16_t))
{
struct tcp_pcb *pcb = NULL;
struct hc_state *state;
static u8_t num = 0;
// local port
u16_t port= 4545;

// Get a place for a new webclient state in the memory
state = malloc(sizeof(struct hc_state));

// Create a new PCB (PROTOCOL CONTROL BLOCK)
pcb = tcp_new();
if(pcb == NULL || state == NULL)
{
//UARTprintf("hc_open: Not enough memory for pcb or state\n");
//Not enough memory
return 0;
}

// Define webclient state vars
num++;
state->Num = num;
state->RecvData = NULL;
state->ConnectionTimeout = 0;
state->Len = 0;
state->ReturnPage = returnpage;

// Make place for PostVars & Page
//if(PostVars != NULL) state->PostVars = malloc(strlen(PostVars) +1);
state->Page = malloc(strlen(Page) +1);

// Check for "out of memory"
if(state->Page == NULL)
{
free(state->Page);
//free(state->PostVars);
free(state);
tcp_close(pcb);
return 0;
}
// Place allocated copy data
strcpy(state->Page, Page);
//if(PostVars != NULL) strcpy(state->PostVars, PostVars);

// Bind to local IP & local port
while(tcp_bind(pcb, IP_ADDR_ANY, port) != ERR_OK)
{
// Local port in use, use port+1
port++;
}

// Use conn -> argument(s)
tcp_arg(pcb, state);

// Open connect (SEND SYN)
tcp_connect(pcb, &remoteIP, 8080, hc_connected);

return num;
}
//==============================================================================


webclient.h
CODE
#ifndef __WEBCLIENT_H
#define __WEBCLIENT_H

/* The unsigned data types */
typedef unsigned char u8_t;
typedef unsigned short u16_t;
typedef unsigned int u32_t;

// You can replace this enum for saving MEMORY (replace with define's)
typedef enum
{
OK,
OUT_MEM,
TIMEOUT,
NOT_FOUND,
GEN_ERROR
} hc_errormsg;

struct hc_state {
u8_t Num;
char *Page;
//char *PostVars;
char *RecvData;
u16_t Len;
u8_t ConnectionTimeout;
void (* ReturnPage)(u8_t num, hc_errormsg, char *data, u16_t len);
};

// Public function
int hc_open(struct ip_addr, char *, char *, void (*)(u8_t, hc_errormsg, char *, u16_t));

#endif // __WEBCLIENT_H


Заранее спасибо за любые советы.

Сообщение отредактировал IgorKossak - Feb 20 2014, 19:32
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 08:40
Рейтинг@Mail.ru


Страница сгенерированна за 0.01269 секунд с 7
ELECTRONIX ©2004-2016