Parsing html response in RENESAS MCU.

Parsing html response in RENESAS MCU.

Witalij Puhalski

Often there is a need for devices to embed a web server for device configuration. All operations have been tested by me on the demo version of S7G2 Renesas. Why Renesas? 1. At work, we use the processors of the given brand 2. The development framework from Renesas(SSP) is a revolution in the sphere of writing programs for embed (editor’s opinion, not advertising :)) I will not jump and install the e2 studio programming environment — I will just say that version must be Version: 5.4.0.023 not Above. We create a new project and have a new thread (yes, use RTOS in Renesas use ThreadX RTOS :)) Add new thread and give some name for ex. Ethernet thread. In the properties of thread set Stack size 4096 — because we add web server and pages.Warning in the properties of g_packet_pool NetX change property Packet Size to 1568 bytes Than add Http Server to the thread — XWare — NetX — Protocols — HTTP SERVER . Add to our http server Netx IP Instance. Press Generate Project Content and lets go to our c code. Add H file with html strings «http_htmlstrings.h» — i will tell why we use htmlstrings — we create RamDisk for storing our html pages.You can add your page configuration — use http://tomeko.net/online_tools/cpp_text_escape.php?lang=en for add yor html in c view. Go to the ethernet thread — my code of etht thread. My code of thread — is

#include «eth_thread.h»
#include «pin_ports.h»
//NX_SNTP

#include «nx_api.h»
#include «nx_ip.h»
#include «nx_sntp_client.h»
//HTML STRINGS

#include «http_htmlstrings.h»
extern TX_THREAD port_1_thread;
extern TX_THREAD SDCardThread;
uint8_t data_ip[] = «»;
bool pagereturned = false;

//Breakpoint redifinition. Breakpoint work only in Debug Mode
#
define _BKPT() if (CoreDebug — > DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) __BKPT(0)# define MAX_HTTP_BUFFER_SIZE 40
//Status EROOR
ssp_err_t status;
ULONG ip_status, ip_address, ip_mask, server_ip;
//HTTP SERVER
NX_HTTP_SERVER HTTP_Server;
CHAR NETX_SVR[8192];
UCHAR RamDisk_mem[1024 * 32];
UCHAR RamDisk_sector_cache[2048];
FX_MEDIA RamDisk;
extern VOID _fx_ram_driver(FX_MEDIA * media_ptr);
UINT htmlresponsesize = 665;
UINT HTTPServerStart(void);
UINT RamDiskCreate(void);#
define DHCP_USE 0# define STATIC_IP_USE 1

/* server 0.sg.pool.ntp.org */
# define NTP_SERVER_IP IP_ADDRESS(202, 73, 57, 107)

//Printf debug console settings
# define USE_SEMIHOSTING#
if defined(__GNUC__) /* GCC Compiler */
extern void initialise_monitor_handles(void);#
endif

UINT request_notify(NX_HTTP_SERVER * server_ptr, UINT request_type, CHAR * resource, NX_PACKET * packet_ptr);
UINT authentication_check(struct NX_HTTP_SERVER_STRUCT * server_ptr, UINT request_type, CHAR * resource, CHAR * * name, CHAR * * password, CHAR * * realm);
oid eth_thread_entry(void) {
//Virtual console Settings
if (CoreDebug — > DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) {
initialise_monitor_handles();
printf(«START!\n»);
}

g_ioport.p_api — > pinWrite(POWER_ON_PIN, IOPORT_LEVEL_HIGH);

//Ethernet check procedure if ok — than start Ports
status = nx_ip_status_check( & g_IP_INST, NX_IP_LINK_ENABLED, & ip_status, NX_WAIT_FOREVER);

#
if DHCP_USE
//Start the DHCP
status = nx_dhcp_start( & g_dhcp_client);
if (NX_SUCCESS != status) {
g_ioport.p_api — > pinWrite(ALARM_PIN, IOPORT_LEVEL_HIGH);
}
if (NX_SUCCESS == status) {
/* Start DHCP client and wait for IP address from DHCP server. Time for waiting 3s*/
status = nx_ip_status_check( & g_IP_INST, NX_IP_ADDRESS_RESOLVED, & ip_status, 300);
if (NX_SUCCESS != status) {
_BKPT();
g_ioport.p_api — > pinWrite(ALARM_PIN, IOPORT_LEVEL_HIGH);
}
if (NX_SUCCESS == status)
if (NX_SUCCESS == status) {
if (CoreDebug — > DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) {

printf(«IP ADDRESS: %lu.%lu.%lu.%lu\r\n», (ip_address >> 24) & 0xFF,
(ip_address >> 16) & 0xFF,
(ip_address >> 8) & 0xFF,
(ip_address) & 0xFF);
g_ioport.p_api — > pinWrite(ETH_LINK_PIN, IOPORT_LEVEL_HIGH);

}
}
}
}#
endif

#
if STATIC_IP_USE
if (NX_SUCCESS == status) {
status = nx_ip_address_set( & g_IP_INST, IP_ADDRESS(192, 168, 0, 55), (255, 255, 255, 0)); //BEDZIE POBRANY Z USTAWIEN Z FLASH
if (NX_SUCCESS == status) {
//CREATE RAMDISK
status = RamDiskCreate();
if (FX_SUCCESS != status) {
_BKPT();
}
//START HTTP SERVER
status = HTTPServerStart();
if (FX_SUCCESS != status) {
_BKPT();
}
}
}#
endif

//IF LINK SUCCESS-THAN START Ports Threads
if (NX_SUCCESS == status) {

status = tx_thread_resume( & port_1_thread);
if (NX_SUCCESS != status) {
_BKPT();
g_ioport.p_api — > pinWrite(ALARM_PIN, IOPORT_LEVEL_HIGH);
}
//status = tx_thread_resume(&port_2_thread);
if (NX_SUCCESS != status) {
_BKPT();
}
//status = tx_thread_resume(&netStateCheckThread);
if (NX_SUCCESS != status) {
_BKPT();
}

}
while (1) {
tx_thread_sleep(1);
}
}

UINT app_http_request(NX_HTTP_SERVER * server_ptr, UINT request_type, CHAR * resource, NX_PACKET * packet_ptr) {
NX_PACKET * rep_packet_ptr = NULL;
SSP_PARAMETER_NOT_USED(request_type);
SSP_PARAMETER_NOT_USED(packet_ptr);
CHAR http_buffer[MAX_HTTP_BUFFER_SIZE];
UINT content_length;
UINT actual_size = 0;
UINT paramToGet = 0;

if (strcmp((const char * ) resource, (const char * )
«/») == 0) {
nx_http_server_callback_data_send(server_ptr, (void * ) htmlstrona_main, sizeof(htmlstrona_main));
return (NX_HTTP_CALLBACK_COMPLETED);
}
if (strcmp((const char * ) resource, (const char * )
«/IPsettings.html») == 0) {
if (NX_HTTP_SERVER_POST_REQUEST == request_type) {
int ip_1_oktet, ip_2_oktet, ip_3_oktet, ip_4_oktet;
int mask_1_part, mask_2_part, mask_3_part, mask_4_part;
//nx_http_server_callback_response_send(server_ptr,»POST NOT ALLOWED», «POST DETECTED», NULL);
content_length = nx_http_server_content_length_get(packet_ptr);
nx_http_server_content_get(server_ptr, packet_ptr, 0, http_buffer, content_length, & actual_size);
//IP parse part
http_buffer[actual_size] = ‘\0’;
char * ptr1, * ptr2, * ptr3, * ptr4, * ptr5;
char * ptrm1, * ptrm2, * ptrm3, * ptrm4, * ptrm5;
ptr1 = strchr(http_buffer, ‘=’) + 1;
ptr2 = strchr(ptr1, ‘.’); * ptr2 = 0;
++ptr2;
ptr3 = strchr(ptr2, ‘.’); * ptr3 = 0;
++ptr3;
ptr4 = strchr(ptr3, ‘.’); * ptr4 = 0;
++ptr4;
ptr5 = strchr(ptr4, ‘&’); * ptr5 = 0;

if (isdigit( * ptr1) && isdigit( * ptr2) && isdigit( * ptr3) && isdigit( * ptr4)) {
ip_1_oktet = atoi(ptr1);
ip_2_oktet = atoi(ptr2);
ip_3_oktet = atoi(ptr3);
ip_4_oktet = atoi(ptr4);
if (CoreDebug — > DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) {
printf(«IP ADDRESS: %lu.%lu.%lu.%lu\r\n», ip_1_oktet, ip_2_oktet, ip_3_oktet, ip_4_oktet);
}

}
//MASK PARSE SECTION
ptr5++;
ptrm1 = strchr(ptr5, ‘=’);
++ptrm1;
ptrm2 = strchr(ptrm1, ‘.’); * ptrm2 = 0;
++ptrm2;
ptrm3 = strchr(ptrm2, ‘.’); * ptrm3 = 0;
++ptrm3;
ptrm4 = strchr(ptrm3, ‘.’); * ptrm4 = 0;
++ptrm4;
ptrm5 = strchr(ptrm4, ‘&’); * ptrm5 = 0;
if (isdigit( * ptrm1) && isdigit( * ptrm2) && isdigit( * ptrm3) && isdigit( * ptrm4)) {
mask_1_part = atoi(ptrm1);
mask_2_part = atoi(ptrm2);
mask_3_part = atoi(ptrm3);
mask_4_part = atoi(ptrm4);
if (CoreDebug — > DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) {
printf(«IP MASK: %lu.%lu.%lu.%lu\r\n», mask_1_part, mask_2_part, mask_3_part, mask_4_part);
}
status = nx_http_server_callback_data_send(server_ptr, (void * ) htmlstrona_success_changes, sizeof(htmlstrona_success_changes));
if (NX_SUCCESS != status) {

}
status = nx_ip_address_set( & g_IP_INST, IP_ADDRESS(ip_1_oktet, ip_2_oktet, ip_3_oktet, ip_4_oktet), (mask_1_part, mask_2_part, mask_3_part, mask_4_part));
if (NX_SUCCESS != status) {

}
return (NX_HTTP_CALLBACK_COMPLETED);
}

}
if (NX_HTTP_SERVER_GET_REQUEST == request_type) {

}

nx_http_server_callback_data_send(server_ptr, (void * ) htmlstrona_rssettings, sizeof(htmlstrona_rssettings));
return (NX_HTTP_CALLBACK_COMPLETED);
}
pagereturned = false;
return (NX_SUCCESS);
}
UINT authentication_check(struct NX_HTTP_SERVER_STRUCT * server_ptr, UINT request_type, CHAR * resource, CHAR * * name, CHAR * * password, CHAR * * realm) {

SSP_PARAMETER_NOT_USED(resource);
SSP_PARAMETER_NOT_USED(request_type);
SSP_PARAMETER_NOT_USED(server_ptr);
SSP_PARAMETER_NOT_USED(name);
SSP_PARAMETER_NOT_USED(password);
SSP_PARAMETER_NOT_USED(realm);
return (NX_SUCCESS);
}
UINT HTTPServerStart() {
//Start http Server
status = nx_http_server_create( & HTTP_Server, (CHAR * )
«HTTP Server», & g_IP_INST, & RamDisk, & NETX_SVR, 4096, & g_packet_pool0, authentication_check, app_http_request);
if (status != NX_SUCCESS) {
//DIODA ALARM ON
}

status = nx_http_server_start( & HTTP_Server);
if (status == NX_SUCCESS) {

}
return (NX_SUCCESS);

}

UINT RamDiskCreate() {
//Create Ramdisk Storage
status = fx_media_format( & RamDisk,
_fx_ram_driver, /* Driver entry */
RamDisk_mem, /* RAM disk memory pointer */
RamDisk_sector_cache, /* Media buffer pointer */
sizeof(RamDisk_sector_cache), /* Media buffer size */
(CHAR * )
«RAM_DISK_WWW», /* Volume Name */
1, /* Number of FATs */
64, /* Directory Entries */
0, /* Hidden sectors */
512, /* Total sectors */
256, /* Sector size */
1, /* Sectors per cluster */
1, /* Heads */
1); /* Sectors per track */
//Open Ram_Disk
status = fx_media_open( & RamDisk, (CHAR * )
«RAM DISK», _fx_ram_driver, RamDisk_mem, RamDisk_sector_cache, sizeof(RamDisk_sector_cache));
if (status == FX_SUCCESS) {

}
return (FX_SUCCESS);

}



Lets analize the code

1.First i check if the connection of cable is present in status = nx_ip_status_check(&g_IP_INST, NX_IP_LINK_ENABLED, &ip_status, NX_WAIT_FOREVER);

2. I check if DHCP USING i will print which address assigned for me but if i using IP STATIC IP — than i set static ip to connect in future to my device. status = nx_ip_address_set(&g_IP_INST, IP_ADDRESS(192,168,0,55),(255,255,255,0));

3. Create RAMDISK and HTTP SERVER function So my Http port is started.

Go to the browser and input our IP https://www.linkedin.com/redir/invalid-link-page?url=192%2e168%2e0%2e55 . — IP Settings. Lets analize code to parsing POST query to our web server page. Our callback Method is name app_http_request() in this method we can parsing our post request in section if (NX_HTTP_SERVER_POST_REQUEST == request_type ) and set new ip address for our device with method status = nx_ip_address_set(&g_IP_INST, IP_ADDRESS(ip_1_oktet,ip_2_oktet,ip_3_oktet,ip_4_oktet),(mask_1_part,mask_2_part,mask_3_part,mask_4_part));