Webserver only w/o any other functions, single thread. Running on STM32F013+W5500
Dependencies: NTPClient W5500Interface Watchdog device_configuration eeprom_flash mbed-rpc-nucleo mbed-rtos mbed
Fork of F103-Serial-to-Ethernet by
Revision 31:2e4b6de6c2f3, committed 2015-01-24
- Comitter:
- olympux
- Date:
- Sat Jan 24 20:49:24 2015 +0000
- Parent:
- 30:15e23257e786
- Child:
- 32:db2e8ea06ee1
- Commit message:
- Process both RPC and NNIO control commands with UDP and TCP
Changed in this revision
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
readme.txt | Show annotated file Show diff for this revision Revisions of this file |
--- a/main.cpp Sun Jan 11 13:53:53 2015 +0000 +++ b/main.cpp Sat Jan 24 20:49:24 2015 +0000 @@ -14,20 +14,20 @@ #include "Watchdog.h" -//Debug is disabled by default +/** Debug option + * + */ #if 1 //Enable debug #include <cstdio> -#define DBG(x, ...) std::printf("[main : DBG]"x"\r\n", ##__VA_ARGS__); -#define WARN(x, ...) std::printf("[main : WARN]"x"\r\n", ##__VA_ARGS__); -#define ERR(x, ...) std::printf("[main : ERR]"x"\r\n", ##__VA_ARGS__); - +#define DBG(x, ...) std::printf("[main : DBG]"x"\r\n", ##__VA_ARGS__); +#define WARN(x, ...) std::printf("[main : WARN]"x"\r\n", ##__VA_ARGS__); +#define ERR(x, ...) std::printf("[main : ERR]"x"\r\n", ##__VA_ARGS__); #else //Disable debug -#define DBG(x, ...) +#define DBG(x, ...) #define WARN(x, ...) -#define ERR(x, ...) - +#define ERR(x, ...) #endif @@ -49,18 +49,18 @@ 0x5212, // UDP server port, not used 0x8888, // 1st run? 0xA5A5 = configured 0x6212, 0x6313, 0x6414, // MAC - + // this section is for the TCP server that this device connects to in TCP client mode 0x7212, 0x7313, // 0xA5A5 = auto transmit status, time period 0x8212, 0x8313,0x8414, 0x8515, // TCP server IP address 0x9212, // TCP server port - + // this section is for selecting protocol, not used 0xA212, // 0xA5A5 = enable TCP server 0xA313, // 0xA5A5 = eanble TCP client 0xA414 // 0xA5A5 = enable UDP server - }; - + }; + /* * Network configuration @@ -110,11 +110,9 @@ uint16_t u16enable_tcp_client, u16enable_tcp_server;// flags for enabling TCP client or TCP server #define NET_BUF_LEN 256 -#define RPC_BUF_LEN 256 char tcp_receiving_buffer[NET_BUF_LEN]; -char tcp_sending_buffer[NET_BUF_LEN]; // socket buffer char udp_receiving_buffer[NET_BUF_LEN]; -char rpc_outbuf[RPC_BUF_LEN]; // rpc output buffer +char network_output_buffer[NET_BUF_LEN]; // output buffer for TCP/UDP control command /* @@ -251,10 +249,11 @@ /* * Threads */ -// Timer thread for auto update -void auto_update_timer_thread(void const* args) { +// Timer thread for auto update in TCP client function +void auto_update_timer_thread(void const* args) +{ bool update_flag = true; - + Thread::wait(500); while(true) { auto_update_queue.put(&update_flag); @@ -264,7 +263,8 @@ // WDT reset -void wdt_reset_thread(void const* args) { +void wdt_reset_thread(void const* args) +{ while (true) wdt.Service(); } @@ -273,31 +273,32 @@ int main() { int n, ret; - + Thread::wait(500); // turn on delay - + /* * Configure */ uart.baud(115200); DBG("\r\nStarting..."); - + + // check watchdog if (wdt.WatchdogCausedReset()) DBG("Watchdog caused reset."); wdt.Configure(4); - + /* * FLASH */ load_eeprom_network(); load_eeprom_tcpserver(); - + /* * UI threads */ Thread t2(auto_update_timer_thread); Thread t3(wdt_reset_thread); - + /* * Ethernet */ @@ -306,13 +307,13 @@ ERR("Ethernet initialisation failed. App halted."); while (true) {}; } - + Thread::wait(2000); // TCP/UDP stack delay -/* -* UDP server -* TCP server/client -*/ + /* + * UDP server + * TCP server/client + */ #ifdef UDP_SERVER ret = udp_server.bind(udp_server_local_port); DBG("UDP server started (sock.bind = %d)...", ret); @@ -329,7 +330,7 @@ #ifdef TCP_CLIENT #endif - + /* * Network loop processor */ @@ -341,21 +342,20 @@ ret = tcp_sock.connect(str_server_ip_addr, u16tcp_server_port); // timeout is default in connect() in W5500.h if (ret > -1) { DBG("Successfully connected to %s on port %d", str_server_ip_addr, u16tcp_server_port); - } - else { + } else { ERR("Unable to connect to %s on port %d", str_server_ip_addr, u16tcp_server_port); } } - + // transmit data if connected if (tcp_sock.is_connected()) { osEvent evt = auto_update_queue.get(1); // timeout after 1ms if (evt.status == osEventMessage) { DBG("Updating..."); - update_sending_frame(tcp_sending_buffer); - tcp_sock.send_all(tcp_sending_buffer, SENDING_PROTOCOL_LENGTH); + update_sending_frame(network_output_buffer); + tcp_sock.send_all(network_output_buffer, SENDING_PROTOCOL_LENGTH); } - + // check to receive or timeout tcp_sock.set_blocking(false, TCP_CLIENT_RECEIVE_TIMEOUT); n = tcp_sock.receive(tcp_receiving_buffer, sizeof(tcp_receiving_buffer)); @@ -374,26 +374,37 @@ if (1) { // wait for client within timeout ret = tcp_server.accept(tcp_client); - + // tcp client connected if (ret > -1) { DBG("Connection from: %s", tcp_client.get_address()); - + // loop waiting and receiving data within timeout tcp_client.set_blocking(false, TCP_SERVER_RECEIVE_TIMEOUT); // Timeout after x seconds - while (true) { + while (tcp_client.is_connected()) { n = tcp_client.receive(tcp_receiving_buffer, sizeof(tcp_receiving_buffer)); if (n <= 0) break; - + // got some data, process it tcp_receiving_buffer[n] = '\0'; // for debugging purpose DBG("TCP server received: %s", tcp_receiving_buffer); n = process_control_command(tcp_receiving_buffer, n); - // send rpc reply back to client, NNIO protocol always returns 0 + // send reply back to client, NNIO protocol always returns 0 + // RPC-style protocol if (n > 0) { - rpc_outbuf[n] = '\0'; - tcp_client.send_all(rpc_outbuf, strlen(rpc_outbuf)); - } + network_output_buffer[n] = '\0'; + tcp_client.send_all(network_output_buffer, strlen(network_output_buffer)); + } // RPC-style protocol + else if (n == 0) { + // then, check query status command and sending protocol if required + if (tcp_receiving_buffer[RECEIVING_PROTOCOL_COMMAND_POS] == QUERY_STATUS_COMMAND) { + DBG("Requested to send device status through TCP"); + // sending protocol + update_sending_frame(network_output_buffer); + tcp_client.send_all(network_output_buffer, SENDING_PROTOCOL_LENGTH); + DBG("Sent"); + } + } // NNIO protocol } // end loop if no data received within timeout } // if client connected tcp_client.close(); @@ -402,9 +413,9 @@ #ifdef UDP_SERVER // configuration and control, both NNIO and RPC-style bool discovery_mode_flag, config_mode_flag; - + n = udp_server.receiveFrom(ep_udp_client, udp_receiving_buffer, sizeof(udp_receiving_buffer)); - + // check to see if it is a query command // if yes, is it a discovery command or an ip query to enter config mode discovery_mode_flag = false; @@ -421,11 +432,10 @@ DBG("Entered configuration mode..."); DBG("!!! RESET when finished"); } // NNCFIP - + // if received NNCFIP, enter config mode if (config_mode_flag) { - while (n > 0) - { + while (n > 0) { // got some data, test it DBG("UDP received (%s) from (%s:%d)", udp_receiving_buffer, ep_udp_client.get_address(), ep_udp_client.get_port()); process_config_command(udp_receiving_buffer, n); @@ -438,9 +448,20 @@ else if ((n > 0) && (!discovery_mode_flag)) { n = process_control_command(udp_receiving_buffer, n); // send rpc reply back to client, NNIO protocol always returns 0 + // RPC-style protocol if (n > 0) { - rpc_outbuf[n] = '\0'; - udp_server.sendTo(ep_udp_client, rpc_outbuf, strlen(rpc_outbuf)); + network_output_buffer[n] = '\0'; + udp_server.sendTo(ep_udp_client, network_output_buffer, strlen(network_output_buffer)); + } // RPC-style protocol + else if (n == 0) { + // then, check query status command and sending protocol if required + if (udp_receiving_buffer[RECEIVING_PROTOCOL_COMMAND_POS] == QUERY_STATUS_COMMAND) { + DBG("Requested to send device status through UDP"); + // sending protocol + update_sending_frame(network_output_buffer); + udp_server.sendTo(ep_udp_client, network_output_buffer, SENDING_PROTOCOL_LENGTH); + DBG("Sent"); + } } } #endif @@ -454,13 +475,13 @@ void process_config_command(char* received_buffer, int len) { DBG("Processing configuration command"); - + // a configuration command always starts with NN if ((received_buffer[0] == 'N') && (received_buffer[1] == 'N') && - (received_buffer[2] == 'C') && (received_buffer[3] == 'F')) { + (received_buffer[2] == 'C') && (received_buffer[3] == 'F')) { switch (len) { - // length = 6, a QUERY command (discovery command, TCP port, or UDP port) - // Format: NNCFDS, NNCFTP, NNCFUP, NNCFTM + // length = 6, a QUERY command (discovery command, TCP port, or UDP port) + // Format: NNCFDS, NNCFTP, NNCFUP, NNCFTM case QUERY_NETWORK_CONFIG_CMD_LENGTH: { if (strstr(received_buffer, QUERY_IP_CMD) != NULL) { udp_server.sendTo(ep_udp_client, eth.getIPAddress(), strlen(eth.getIPAddress())); @@ -564,10 +585,10 @@ char* received_frame; bool rpc_style; int pos; - char inbuf[RPC_BUF_LEN]; - + char inbuf[NET_BUF_LEN]; + DBG("Processing control command"); - + /* * This section is for RPC-style command */ @@ -580,14 +601,13 @@ if ((len > 0) && (inbuf[0] == '/')) { char obj_name[32]; bool result; - + rpc_style = true; // find RPC object name for (int i = 1; i < strlen(inbuf); i++) { if (inbuf[i] != '/') { obj_name[i-1] = inbuf[i]; - } - else { + } else { obj_name[i-1] = '\0'; break; } @@ -596,24 +616,23 @@ /* * execute RPC command, return reply length and reply in rpc_outbuf */ - result = RPC::call(inbuf, rpc_outbuf); + result = RPC::call(inbuf, network_output_buffer); if (result) { // re-arrange output buffer as following: object_name:output_value - strcpy(inbuf, rpc_outbuf); // use inbuf as temp - strcpy(rpc_outbuf, obj_name); // rpc object name - strcat(rpc_outbuf, ":"); - strcat(rpc_outbuf, inbuf); // concat rpc reply - strcat(rpc_outbuf, "\r\n"); // CR-LF - int j = strlen(rpc_outbuf); - DBG("Reply of rpc command on \"%s\" (%d bytes): %s", obj_name, j, rpc_outbuf); + strcpy(inbuf, network_output_buffer); // use inbuf as temp + strcpy(network_output_buffer, obj_name); // rpc object name + strcat(network_output_buffer, ":"); + strcat(network_output_buffer, inbuf); // concat rpc reply + strcat(network_output_buffer, "\r\n"); // CR-LF + int j = strlen(network_output_buffer); + DBG("Reply of rpc command on \"%s\" (%d bytes): %s", obj_name, j, network_output_buffer); return j; // return length of rpc_outbuf - } - else { + } else { ERR("Failed: %s", inbuf); return -1; } } - + /* * This section below is for NNIO protocol */ @@ -627,13 +646,13 @@ } pos = id - received_buffer; DBG("Found a frame at %d", pos); - + // extract this frame received_frame = &received_buffer[pos]; // calculate the rest received_buffer = &received_buffer[pos + RECEIVING_PROTOCOL_LENGTH]; len -= RECEIVING_PROTOCOL_LENGTH; - + // process this received frame // firstly, update outputs if required // digital outputs @@ -662,17 +681,8 @@ str_uart[32] = '\0'; uart.printf("%s\r\n", str_uart); } - - // then, check query status command and sending protocol if required - if (received_frame[RECEIVING_PROTOCOL_COMMAND_POS] == QUERY_STATUS_COMMAND) { - DBG("Requested to send device status through TCP"); - // sending protocol - update_sending_frame(tcp_sending_buffer); - tcp_client.send_all(tcp_sending_buffer, SENDING_PROTOCOL_LENGTH); - DBG("Sent"); - } } - + DBG("Successfully processed."); return 0; } @@ -681,11 +691,12 @@ /* * W5500 Ethernet init */ -int ethernet_init(void) { +int ethernet_init(void) +{ int dhcp_ret, ret; - + DBG("Initialising ethernet..."); - + // if not configured, try dhcp dhcp_ret = -1; if (configured_ip != DEFAULT_ENABLE_FLAG_VALUE) { @@ -694,7 +705,7 @@ if (dhcp_ret == 0) dhcp_ret = eth.connect(); } - + if (dhcp_ret != 0) { DBG("No DHCP, load static IP configuration"); ret = eth.init(u8mac, str_ip_addr, str_ip_subnet, str_ip_gateway); // static @@ -719,7 +730,7 @@ ERR("Error eth.connect() - ret = %d", ret); return -1; } - + return 0; } @@ -727,9 +738,10 @@ /* * Update digital outputs according to receiving protocol */ -void update_digital_outputs(char* buf) { +void update_digital_outputs(char* buf) +{ DBG("Digital outputs: %s", buf); - + dout0 = (buf[0] == DIGITAL_HIGH)? 1 : 0; dout1 = (buf[1] == DIGITAL_HIGH)? 1 : 0; dout2 = (buf[2] == DIGITAL_HIGH)? 1 : 0; @@ -743,11 +755,12 @@ /* * Prepare a frame for sending protocol, which includes status of I/Os */ -void update_sending_frame(char* buf) { +void update_sending_frame(char* buf) +{ memcpy(&buf[SENDING_PROTOCOL_ID_POS], DEVICE_CONTROL_CODE, 4); // device id memcpy(&buf[SENDING_PROTOCOL_MAC_POS], &u8mac, 6); memcpy(&buf[SENDING_PROTOCOL_IP_POS], &u8ip_addr, 4); - + buf[SENDING_PROTOCOL_DI_POS+0] = (din0 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; buf[SENDING_PROTOCOL_DI_POS+1] = (din1 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; buf[SENDING_PROTOCOL_DI_POS+2] = (din2 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; @@ -756,7 +769,7 @@ buf[SENDING_PROTOCOL_DI_POS+5] = (din5 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; buf[SENDING_PROTOCOL_DI_POS+6] = (din6 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; buf[SENDING_PROTOCOL_DI_POS+7] = (din7 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; - + buf[SENDING_PROTOCOL_DO_POS+0] = (dout0 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; buf[SENDING_PROTOCOL_DO_POS+1] = (dout1 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; buf[SENDING_PROTOCOL_DO_POS+2] = (dout2 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; @@ -765,7 +778,7 @@ buf[SENDING_PROTOCOL_DO_POS+5] = (dout5 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; buf[SENDING_PROTOCOL_DO_POS+6] = (dout6 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; buf[SENDING_PROTOCOL_DO_POS+7] = (dout7 == 1) ? DIGITAL_HIGH : DIGITAL_LOW; - + uint16_t val = ain0.read_u16(); // 16-bits normalised memcpy(&buf[SENDING_PROTOCOL_AI0_POS], &val, 2); // LSB MSB val = ain1.read_u16(); // 16-bits normalised
--- a/readme.txt Sun Jan 11 13:53:53 2015 +0000 +++ b/readme.txt Sat Jan 24 20:49:24 2015 +0000 @@ -12,4 +12,8 @@ v1.0 (06/01/2014) + Added: RPC command replies as following object_name:reply_value - + Modified: clean code in my_eeprom_funcs and main.cpp \ No newline at end of file + + Modified: clean code in my_eeprom_funcs and main.cpp + +v1.1 (24/01/2015) + + Modified: control command is able to be processed by both TCP and UDP. + Only one network output buffer is used for RPC-style and NNIO protocols. \ No newline at end of file