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 Chau Vo

main.cpp

Committer:
olympux
Date:
2016-06-16
Revision:
43:48ca8c6f6f49
Parent:
42:d0ff08711ca5
Child:
44:4e8a9b466695

File content as of revision 43:48ca8c6f6f49:

#include "mbed.h"
#include "rtos.h"
#include "mbed_rpc.h"
#include "Arguments.h"

#include "eeprom.h"
#include "EthernetInterface.h"
#include "NTPClient.h"

#include "my_eeprom_funcs.h"
#include "Watchdog.h"

#include "RPCCommand.h"
#include "HTTPServer.h"
#include "Formatter.h"
#include "RequestHandler.h"
#include "RPCType.h"

#define SERVER_PORT 80


/*
 * 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__);
#else
//Disable debug
#define DBG(x, ...)
#define WARN(x, ...)
#define ERR(x, ...)
#endif


/*
* Hardware defines
*/
// Ethernet
SPI spi(PA_7, PA_6, PA_5); // mosi, miso, sclk
EthernetInterface eth(&spi, PA_4, PC_9); // spi, cs, reset
int ethernet_init(void);

/*
* EEPROM section
*/
// Virtual address defined by the user: 0xFFFF value is prohibited
uint16_t VirtAddVarTab[NumbOfVar] = {0x1212, 0x1313, 0x1414, 0x1515, // IP_Addr
                                     0x2212, 0x2313, 0x2414, 0x2515, // IP_Subnet
                                     0x3212, 0x3313, 0x3414, 0x3515, // IP_Gateway
                                     0x4212, // TCP server port, not used
                                     0x5212, // UDP server port, not used
                                     0x8888, // 1st run? 0xA5A5 = static IP has been 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, always enabled for configuration
                                    };


/*
 * Variables for network configuration, TCP server
 */
// Device configuration
uint16_t u16ip_addr[4], u16ip_subnet[4], u16ip_gateway[4], u16mac_addr[3]; // 16-bits, directly loaded from eeprom
char str_ip_addr[16], str_ip_subnet[16], str_ip_gateway[16], str_mac_addr[20]; // for printf and RPC, converted from 16-bits u16ip_xxx
uint8_t u8ip_addr[4];// keep ip address in 8-bits
uint16_t configured_ip = 0;  // flag indicates a static ip has been configured 0xA5A5
uint8_t u8mac[6]; // mac in 8-bits

// TCP/UDP server
uint16_t tcp_server_local_port = 10000; // change to 7000 if internet required
uint16_t udp_server_local_port = 11000;

// TCP client
// this section is used to set the TCP server that this device connects to in TCP client mode.
// this device will update its status to the server every transmit_time_period.
uint16_t auto_transmit_flag = 0, transmit_time_period = 1000; // auto transmit status, time period = 1s
uint16_t u16server_ip_addr[4]; // directly loaded from eeprom
uint8_t u8server_ip_addr[4]; // server ip address in 8-bits
char str_server_ip_addr[16];// for printf, converted from 16-bits u16server_ip_addr
uint16_t u16tcp_server_port; // directly loaded from eeprom
uint16_t u16enable_tcp_server, u16enable_tcp_client;// flags for enabling TCP client or TCP server

// Corresponding RPC variables
RPCVariable<char*> rpcIPAddress(str_ip_addr, 16, "ipaddr");
RPCVariable<char*> rpcSubnet(str_ip_subnet, 16, "subnet");
RPCVariable<char*> rpcGateway(str_ip_gateway, 16, "gateway");
RPCVariable<char*> rpcMac(str_mac_addr, 20, "mac");
RPCVariable<unsigned short> rpcLocalTCPServerPort(&tcp_server_local_port, "localtcpserverport");
RPCVariable<unsigned short> rpcLocalUDPPort(&udp_server_local_port, "localudpport");
RPCVariable<unsigned short> rpcEnableTCPServer(&u16enable_tcp_server, "enabletcpserver");

// RPC function definitions
// Create a function of the required format
void save_ip_addr(Arguments* args, Reply* rep);
void disable_static_ip_addr_flag(Arguments* args, Reply* rep);

void save_ip_addr(Arguments* args, Reply* rep){
    int b[4], n, i;
    char ipaddr[4];
    
    n = sscanf(str_ip_addr, "%d.%d.%d.%d", &b[0], &b[1], &b[2], &b[3]);
    if (n == 4) {
        DBG("%d.%d.%d.%d",b[0],b[1],b[2],b[3]);
        for (i = 0; i < 4; i++) {
            ipaddr[i] = b[i] & 0x00FF;
        }
        save_ip_addr(ipaddr);
        NVIC_SystemReset();
    }
    else {
        DBG("Saving IP address failed");
    }
}
void reset_configuration(Arguments* args, Reply* rep){
    reset_conf();
}
// Attach it to an RPC object
RPCFunction rpcSaveIPAddr(&save_ip_addr, "saveipaddr");
RPCFunction rpcResetConfiguration(&reset_configuration, "resetconf");

// Serial
Serial uart(USBTX,USBRX);
// Watchdog
Watchdog wdt;



/*
 * Threads
 */
// WDT reset
void wdt_reset_thread(void const* args)
{
    while (true)
        wdt.Service();
}


HTTPServer create_simple_server()
{    
    HTTPServer srv;
    srv.add_request_handler("DELETE", new DeleteRequestHandler());
    srv.add_request_handler("GET", new GetRequestHandler());
    srv.add_request_handler("PUT", new PutRequestHandler());
    return srv;
}

HTTPServer create_interactive_server()
{
    HTTPServer srv(new InteractiveHTMLFormatter());
    srv.add_request_handler("GET", new ComplexRequestHandler());
    return srv;
}

// Main code
int main()
{
    int ret;
    
    Thread::wait(500); // turn on delay

    /*
    * Configure
    */
    uart.baud(115200);
    DBG("Starting...");

    // check watchdog
    if (wdt.WatchdogCausedReset())
        DBG("Watchdog caused reset.");
    wdt.Configure(4);

    /*
    * FLASH
    */
    load_eeprom_network();
    load_eeprom_tcpserver();

    /*
    * UI threads
    */
    Thread t3(wdt_reset_thread);
    
    // rpc
    RPCType::instance().register_types();

    /*
    * Ethernet
    */
    ret = ethernet_init();
    if (ret) {
        ERR("Ethernet initialisation failed. App halted.");
        while (true) {};
    }

    Thread::wait(2000); // TCP/UDP stack delay

    // create rpc http server
    HTTPServer srv = create_interactive_server();

    if(!srv.init(SERVER_PORT))
    {
        eth.disconnect();
        return -1;
    }

    srv.run();
}


/*
 * W5500 Ethernet init
 */
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) {
        DBG("Connecting to DHCP server...");
        dhcp_ret = eth.init(u8mac);
        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
    } else {
        snprintf(str_ip_addr, 16, "%s", eth.getIPAddress());
        snprintf(str_ip_subnet, 16, "%s", eth.getNetworkMask());
        snprintf(str_ip_gateway, 16, "%s", eth.getGateway());
        ret = 0;
    }

    if (ret == 0) {
        DBG("Initialized, MAC: %s", eth.getMACAddress());
    } else {
        ERR("Error eth.init() - ret = %d", ret);
        return -1;
    }

    ret = eth.connect();
    if (!ret) {
        DBG("IP: %s, MASK: %s, GW: %s", eth.getIPAddress(), eth.getNetworkMask(), eth.getGateway());
    } else {
        ERR("Error eth.connect() - ret = %d", ret);
        return -1;
    }

    return 0;
}