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-08-19
Revision:
47:d92d2c5b8073
Parent:
46:971bdaa3507c

File content as of revision 47:d92d2c5b8073:

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

#include "EthernetInterface.h"
#include "NTPClient.h"
#include "Watchdog.h"

#include "eeprom_flash.h"
#include "device_configuration.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);

Serial pc(USBTX,USBRX);
Watchdog wdt;


/*
 * Variables for network configuration
 */
// Device configuration
extern uint16_t u16IpAddr[4], u16IpSubnet[4], u16IpGateway[4], u16MacAddr[3]; // 16-bits variables to be compatible with eeprom functions
extern char strIpAddr[16], strIpSubnet[16], strIpGateway[16], strMacAddr[20]; // RPC variables, converted from 16-bits u16ip_xxx
extern uint16_t u16DeviceConfiguredFlag;  // flag indicates whether device has been configured (0xA5A5) or not
// TCP server/UDP
extern uint16_t u16LocalTcpServerPort;
extern uint16_t u16LocalUdpPort;
// TCP client mode, set parameters of the remote TCP server this device connects to.
// When enabled, this device will send its status to the server every transmit_time_period.
extern uint16_t u16RemoteTcpServerIpAddr[4]; // 16-bit variable to be compatible with eeprom functions
extern char strRemoteTcpServerIpAddr[16]; // RPC variable, converted from 16-bits u16server_ip_addr
extern uint16_t u16RemoteTcpServerPort; // 16-bit variable to be compatible with eeprom functions
extern uint16_t u16AutoTransmitFlag, u16TransmitPeriod; // auto transmit status, time period = 1s
// enable modes
extern uint16_t u16EnableTcpServer, u16EnableTcpClient, u16EnableUdp; // flags for enabling TCP server/client and UDP (UDP is always on for configuration)
// extra
extern uint8_t u8IpAddr[4]; // keep device ip address in 8-bits
extern uint8_t u8MacAddr[6]; // keep mac in 8-bits
extern uint8_t u8RemoteTcpServerIpAddr[4]; // remote TCP server ip address in 8-bits


// Corresponding RPC variables
RPCVariable<char*> rpcIPAddress(strIpAddr, 16, "ipaddr");
RPCVariable<char*> rpcSubnet(strIpSubnet, 16, "subnet");
RPCVariable<char*> rpcGateway(strIpGateway, 16, "gateway");
RPCVariable<char*> rpcMac(strMacAddr, 20, "mac");
RPCVariable<unsigned short> rpcLocalTCPServerPort(&u16LocalTcpServerPort, "localtcpserverport");
RPCVariable<unsigned short> rpcLocalUDPPort(&u16LocalUdpPort, "localudpport");

RPCVariable<unsigned short> rpcEnableTCPServer(&u16EnableTcpServer, "enabletcpserver");
RPCVariable<unsigned short> rpcEnableTCPClient(&u16EnableTcpClient, "enabletcpclient");
RPCVariable<unsigned short> rpcEnableUDP(&u16EnableUdp, "enableudp");

RPCVariable<char*> rpcRemoteTCPServerIPAddress(strRemoteTcpServerIpAddr, 16, "remotetcpserveripaddr");
RPCVariable<unsigned short> rpcRemoteTCPServerPort(&u16RemoteTcpServerPort, "remotetcpserverport");
RPCVariable<unsigned short> rpcAutoTransmit(&u16AutoTransmitFlag, "autotransmit");
RPCVariable<unsigned short> rpcTransmitPeriod(&u16TransmitPeriod, "transmitperiod");

// RPC function definitions
// save ip address only
void show_device_config(Arguments* args, Reply* rep){
    DBG("IP: %s", strIpAddr);
    DBG("Subnet: %s", strIpSubnet);
    DBG("Gateway: %s", strIpGateway);
    DBG("MAC: %s", strMacAddr);
}
// Attach eeprom functions to RPC functions
RPCFunction rpcShowConfig(&show_device_config, "showdevconf");

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

/*
 * HTTP server
 */
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 hardware
     */
    pc.baud(115200);
    DBG("Starting...");

    // check watchdog
    if (wdt.WatchdogCausedReset())
        DBG("Watchdog caused reset.");
    wdt.Configure(4);
    
    /*reset_device_configuration();
    uint16_t ip[4] = {192,168,0,120};
    uint16_t subnet[4] = {255,255,255,0};
    uint16_t gateway[4] = {192,168,0,1};
    uint16_t mac[3] = {0,0,1};
    uint16_t tcp_port = DEFAULT_LOCAL_TCP_SERVER_PORT;
    uint16_t udp_port = DEFAULT_LOCAL_UDP_PORT;
    uint16_t remote_ip[4] = {0,0,0,0};
    uint16_t remote_port = 12000;
    uint16_t auto_transmit = DEFAULT_DISABLE_FLAG_VALUE;
    uint16_t transmit_period = 1000;
    uint16_t enable_tcp_server = DEFAULT_DISABLE_FLAG_VALUE;
    uint16_t enable_tcp_client = DEFAULT_DISABLE_FLAG_VALUE;
    uint16_t enable_udp = DEFAULT_ENABLE_FLAG_VALUE;
    
    write_device_configuration(ip, subnet, gateway, mac,
            tcp_port, udp_port,
            remote_ip, remote_port, auto_transmit, transmit_period,
            enable_tcp_server, enable_tcp_client, enable_udp);*/
    
    read_device_configuration();
    
    
    /*
     * Threads
     */
    Thread t0(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
    
    /*
     * HTTP server
     */
    // 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 (u16DeviceConfiguredFlag != DEFAULT_ENABLE_FLAG_VALUE) {
        DBG("Connecting to DHCP server...");
        dhcp_ret = eth.init(u8MacAddr);
        if (dhcp_ret == 0)
            dhcp_ret = eth.connect();
    }

    if (dhcp_ret != 0) {
        DBG("No DHCP, load static IP configuration");
        ret = eth.init(u8MacAddr, strIpAddr, strIpSubnet, strIpGateway); // static
    } else {
        snprintf(strIpAddr, 16, "%s", eth.getIPAddress());
        snprintf(strIpSubnet, 16, "%s", eth.getNetworkMask());
        snprintf(strIpGateway, 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;
}