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 45:8d18a95fcf8a, committed 2016-07-19
- Comitter:
- olympux
- Date:
- Tue Jul 19 07:50:53 2016 +0000
- Parent:
- 44:4e8a9b466695
- Child:
- 46:971bdaa3507c
- Commit message:
- Tested
Changed in this revision
--- a/Formatter.cpp Thu Jun 16 21:51:38 2016 +0000 +++ b/Formatter.cpp Tue Jul 19 07:50:53 2016 +0000 @@ -138,7 +138,7 @@ </head> \ <body>"; -const char* INTERACTIVE_HTML_CODE_2 = "<h3>Device Configuration</h3>\ +const char* INTERACTIVE_HTML_CODE_2 = "<h3>Device Configuration (not yet)</h3>\ <form>\ IP (x.x.x.x): <input type=\"text\" id=\"ipadd\"><br>\ Subnet (x.x.x.x): <input type=\"text\" id=\"subnet\"><br>\
--- a/README.md Thu Jun 16 21:51:38 2016 +0000 +++ b/README.md Tue Jul 19 07:50:53 2016 +0000 @@ -15,11 +15,19 @@ Initial version +Features + - Use eeprom for device configuration - HTTP server - RPC over HTTP: + Support creating objects including AnalogIn + Support RPC string variable +- Additional RPC commands: + + Set ip address: /ipaddr/write 192.168.0.121 + + Save ip address: /saveipaddr/run + + Enable configured flag: /setconf/run + + Disable configured flag: /resetconf/run + Bug fixes
--- a/main.cpp Thu Jun 16 21:51:38 2016 +0000 +++ b/main.cpp Tue Jul 19 07:50:53 2016 +0000 @@ -37,16 +37,16 @@ /* -* Hardware defines -*/ + * 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 -*/ + * 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 @@ -72,9 +72,9 @@ * 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 u16ip_addr[4], u16ip_subnet[4], u16ip_gateway[4], u16mac_addr[3]; // 16-bits variables to be compatible with eeprom functions +char str_ip_addr[16], str_ip_subnet[16], str_ip_gateway[16], str_mac_addr[20]; // RPC variables, 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 @@ -82,31 +82,28 @@ uint16_t tcp_server_local_port = 10000; // change to 7000 if internet required uint16_t udp_server_local_port = 11000; -// TCP client +// Used for TCP client mode // 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 +uint16_t u16server_ip_addr[4]; // 16-bit variable to be compatible with eeprom functions 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 +char str_server_ip_addr[16]; // RPC variable, converted from 16-bits u16server_ip_addr +uint16_t u16tcp_server_port; // 16-bit variable to be compatible with eeprom functions +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> rpcLocalTCPServerPort(&tcp_server_local_port, "localtcpserverport"); RPCVariable<unsigned short> rpcLocalUDPPort(&udp_server_local_port, "localudpport"); -RPCVariable<unsigned short> rpcEnableTCPServer(&u16enable_tcp_server, "enabletcpserver"); +//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){ +// save ip address only +void set_ip_addr(Arguments* args, Reply* rep){ int b[4], n, i; char ipaddr[4]; @@ -123,23 +120,130 @@ DBG("Saving IP address failed"); } } -void set_configuration(Arguments* args, Reply* rep){ + +// set configuration flag +void set_configuration_flag(Arguments* args, Reply* rep){ set_conf(); } -void reset_configuration(Arguments* args, Reply* rep){ + +// reset configuration flag +void reset_configuration_flag(Arguments* args, Reply* rep){ reset_conf(); } -// Attach it to an RPC object -RPCFunction rpcSaveIPAddr(&save_ip_addr, "saveipaddr"); -RPCFunction rpcSetConfiguration(&set_configuration, "setconf"); -RPCFunction rpcResetConfiguration(&reset_configuration, "resetconf"); + +// Attach eeprom functions to RPC functions +RPCFunction rpcSaveIPAddr(&set_ip_addr, "saveipaddr"); +RPCFunction rpcSetConfiguration(&set_configuration_flag, "setconf"); +RPCFunction rpcResetConfiguration(&reset_configuration_flag, "resetconf"); + +/* + * RPC Protocol + * Use the RPC enabled wrapped class - see RpcClasses.h for more info + */ +// DigitalIn +RpcDigitalIn di0(PB_14, "di0"); +RpcDigitalIn di1(PB_12, "di1"); +RpcDigitalIn di2(PB_10, "di2"); +RpcDigitalIn di3(PB_1, "di3"); +RpcDigitalIn di4(PB_15, "di4"); +RpcDigitalIn di5(PB_13, "di5"); +RpcDigitalIn di6(PB_11, "di6"); +RpcDigitalIn di7(PB_2, "di7"); +DigitalIn din0(PB_14); +DigitalIn din1(PB_12); +DigitalIn din2(PB_10); +DigitalIn din3(PB_1); +DigitalIn din4(PB_15); +DigitalIn din5(PB_13); +DigitalIn din6(PB_11); +DigitalIn din7(PB_2); +// DigitalOut +RpcDigitalOut do0(PB_3, "do0"); +RpcDigitalOut do1(PB_5, "do1"); +RpcDigitalOut do2(PB_7, "do2"); +RpcDigitalOut do3(PB_9, "do3"); +RpcDigitalOut do4(PD_2, "do4"); +RpcDigitalOut do5(PB_4, "do5"); +RpcDigitalOut do6(PB_6, "do6"); +RpcDigitalOut do7(PB_8, "do7"); +DigitalOut dout0(PB_3); +DigitalOut dout1(PB_5); +DigitalOut dout2(PB_7); +DigitalOut dout3(PB_9); +DigitalOut dout4(PD_2); +DigitalOut dout5(PB_4); +DigitalOut dout6(PB_6); +DigitalOut dout7(PB_8); +// AnalogIn +RpcAnalogIn adc10(PC_0, "ai0"); // adc10 +RpcAnalogIn adc11(PC_1, "ai1"); // adc11 +AnalogIn ain0(PC_0); +AnalogIn ain1(PC_1); +// AnalogOut, PWM +RpcPwmOut pwm11(PA_8, "pwm0"); // pwm11 +RpcPwmOut pwm21(PA_15, "pwm1"); // pwm21 // Serial +RpcSerial rpcUsart(USBTX, USBRX, "uart"); // usart2 Serial uart(USBTX,USBRX); +// Timer +RpcTimer timer1("tmr1"); // Watchdog Watchdog wdt; +// Some variable types that can be modified through RPC. +//int wheelsOn; +//char lcdBannerMessage; +//float speed; +int current_time; +int enable_onoff_dout = 0; // 8-bit LSB +int do0OnTime = 64800, do0OffTime = 21600; //default ON = 18:00, OFF = 6:00 +int do1OnTime = 64800, do1OffTime = 21600; +int do2OnTime = 64800, do2OffTime = 21600; +int do3OnTime = 64800, do3OffTime = 21600; +int do4OnTime = 64800, do4OffTime = 21600; +int do5OnTime = 64800, do5OffTime = 21600; +int do6OnTime = 64800, do6OffTime = 21600; +int do7OnTime = 64800, do7OffTime = 21600; + +//RPCVariable<int> rpcLights(&wheelsOn, "wheels"); +//RPCVariable<char> rpcBanner(&lcdBannerMessage, "banner"); +//RPCVariable<float> rpcSpeed(&speed, "speed"); +RPCVariable<int> rpcCurrentTime(¤t_time, "Time"); +RPCVariable<int> rpcEnableOnOffDout(&enable_onoff_dout, "EnableOnOffDout"); +RPCVariable<int> rpcdo0OnTime(&do0OnTime, "do0OnTime"); +RPCVariable<int> rpcdo0OffTime(&do0OffTime, "do0OffTime"); +RPCVariable<int> rpcdo1OnTime(&do1OnTime, "do1OnTime"); +RPCVariable<int> rpcdo1OffTime(&do1OffTime, "do1OffTime"); +RPCVariable<int> rpcdo2OnTime(&do2OnTime, "do2OnTime"); +RPCVariable<int> rpcdo2OffTime(&do2OffTime, "do2OffTime"); +RPCVariable<int> rpcdo3OnTime(&do3OnTime, "do3OnTime"); +RPCVariable<int> rpcdo3OffTime(&do3OffTime, "do3OffTime"); +RPCVariable<int> rpcdo4OnTime(&do4OnTime, "do4OnTime"); +RPCVariable<int> rpcdo4OffTime(&do4OffTime, "do4OffTime"); +RPCVariable<int> rpcdo5OnTime(&do5OnTime, "do5OnTime"); +RPCVariable<int> rpcdo5OffTime(&do5OffTime, "do5OffTime"); +RPCVariable<int> rpcdo6OnTime(&do6OnTime, "do6OnTime"); +RPCVariable<int> rpcdo6OffTime(&do6OffTime, "do6OffTime"); +RPCVariable<int> rpcdo7OnTime(&do7OnTime, "do7OnTime"); +RPCVariable<int> rpcdo7OffTime(&do7OffTime, "do7OffTime"); + +// RPC function definitions +// Create a function of the required format +void set_current_time(Arguments* args, Reply* rep); +void set_current_time(Arguments* args, Reply* rep){ + time_t ct = (time_t)current_time; // convert + struct tm *st = localtime(&ct); + + set_time(ct); // set time + + DBG("Set current time to: %s", ctime(&ct)); + DBG("Time only: %d:%d:%d", st->tm_hour, st->tm_min, st->tm_sec); +} +// Attach it to an RPC object +RPCFunction rpcSetCurrentTime(&set_current_time, "SetTime"); + /* * Threads @@ -168,6 +272,9 @@ return srv; } +// Prototypes +void digital_outputs_timer_thread(void const* args); + // Main code int main() { @@ -196,6 +303,7 @@ * UI threads */ Thread t3(wdt_reset_thread); + Thread t4(digital_outputs_timer_thread); // rpc RPCType::instance().register_types(); @@ -270,3 +378,372 @@ return 0; } +// Timer thread to check on/off time of digital outputs +void digital_outputs_timer_thread(void const* args) +{ + Thread::wait(700); + + while(true) { + // read current time + time_t seconds = time(NULL); + struct tm *st = localtime(&seconds); + int current_time_in_seconds = 3600*(st->tm_hour) + 60*(st->tm_min) + st->tm_sec; + DBG("Current time: %d:%d:%d", st->tm_hour, st->tm_min, st->tm_sec); + + // check do0 + if ((enable_onoff_dout && 0x01) == 0x01) { + if (do0OnTime < do0OffTime) { + if ((current_time_in_seconds >= do0OnTime) && (current_time_in_seconds < do0OffTime)){ + if (dout0 == 0) { + dout0 = 1; + DBG("do0 ON"); + } + else { + DBG("do0 ON'ed"); + } + } + else { + if (dout0 == 1) { + dout0 = 0; + DBG("do0 OFF'ed"); + } + else { + DBG("do0 OFF"); + } + } + } + else { + if ((current_time_in_seconds >= do0OffTime) && ((current_time_in_seconds < do0OnTime))) { + if (dout0 == 1) { + dout0 = 0; + DBG("do0 OFF"); + } + else { + DBG("do0 OFF'ed"); + } + } + else { + if (dout0 == 0) { + dout0 = 1; + DBG("do0 ON"); + } + else { + DBG("do0 ON'ed"); + } + } + } + } // end check do0 + + // check do1 + if ((enable_onoff_dout && 0x02) == 0x02) { + if (do1OnTime < do1OffTime) { + if ((current_time_in_seconds >= do1OnTime) && (current_time_in_seconds < do1OffTime)){ + if (dout1 == 0) { + dout1 = 1; + DBG("do1 ON"); + } + else { + DBG("do1 ON'ed"); + } + } + else { + if (dout1 == 1) { + dout1 = 0; + DBG("do1 OFF"); + } + else { + DBG("do1 OFF'ed"); + } + } + } + else { + if ((current_time_in_seconds >= do1OffTime) && ((current_time_in_seconds < do1OnTime))) { + if (dout1 == 1) { + dout1 = 0; + DBG("do1 OFF"); + } + else { + DBG("do1 OFF'ed"); + } + } + else { + if (dout1 == 0) { + dout1 = 1; + DBG("do1 ON"); + } + else { + DBG("do1 ON'ed"); + } + } + } + } // end check do1 + + // check do2 + if ((enable_onoff_dout && 0x04) == 0x04) { + if (do2OnTime < do2OffTime) { + if ((current_time_in_seconds >= do2OnTime) && (current_time_in_seconds < do2OffTime)){ + if (dout2 == 0) { + dout2 = 1; + DBG("do2 ON"); + } + else { + DBG("do2 ON'ed"); + } + } + else { + if (dout2 == 1) { + dout2 = 0; + DBG("do2 OFF"); + } + else { + DBG("do2 OFF'ed"); + } + } + } + else { + if ((current_time_in_seconds >= do2OffTime) && ((current_time_in_seconds < do2OnTime))) { + if (dout2 == 1) { + dout2 = 0; + DBG("do2 OFF"); + } + else { + DBG("do2 OFF'ed"); + } + } + else { + if (dout2 == 0) { + dout2 = 1; + DBG("do2 ON"); + } + else { + DBG("do2 ON'ed"); + } + } + } + } // end check do2 + + // check do3 + if ((enable_onoff_dout && 0x08) == 0x08) { + if (do3OnTime < do3OffTime) { + if ((current_time_in_seconds >= do3OnTime) && (current_time_in_seconds < do3OffTime)){ + if (dout3 == 0) { + dout3 = 1; + DBG("do3 ON"); + } + else { + DBG("do3 ON'ed"); + } + } + else { + if (dout3 == 1) { + dout3 = 0; + DBG("do3 OFF"); + } + else { + DBG("do3 OFF'ed"); + } + } + } + else { + if ((current_time_in_seconds >= do3OffTime) && ((current_time_in_seconds < do3OnTime))) { + if (dout3 == 1) { + dout3 = 0; + DBG("do3 OFF"); + } + else { + DBG("do3 OFF'ed"); + } + } + else { + if (dout3 == 0) { + dout3 = 1; + DBG("do3 ON"); + } + else { + DBG("do3 ON'ed"); + } + } + } + } // end check do3 + + // check do4 + if ((enable_onoff_dout && 0x10) == 0x10) { + if (do4OnTime < do4OffTime) { + if ((current_time_in_seconds >= do4OnTime) && (current_time_in_seconds < do4OffTime)){ + if (dout4 == 0) { + dout4 = 1; + DBG("do4 ON"); + } + else { + DBG("do4 ON'ed"); + } + } + else { + if (dout4 == 1) { + dout4 = 0; + DBG("do4 OFF"); + } + else { + DBG("do4 OFF'ed"); + } + } + } + else { + if ((current_time_in_seconds >= do4OffTime) && ((current_time_in_seconds < do4OnTime))) { + if (dout4 == 1) { + dout4 = 0; + DBG("do4 OFF"); + } + else { + DBG("do4 OFF'ed"); + } + } + else { + if (dout4 == 0) { + dout4 = 1; + DBG("do4 ON"); + } + else { + DBG("do4 ON'ed"); + } + } + } + } // end check do4 + + // check do5 + if ((enable_onoff_dout && 0x20) == 0x20) { + if (do5OnTime < do5OffTime) { + if ((current_time_in_seconds >= do5OnTime) && (current_time_in_seconds < do5OffTime)){ + if (dout5 == 0) { + dout5 = 1; + DBG("do5 ON"); + } + else { + DBG("do5 ON'ed"); + } + } + else { + if (dout5 == 1) { + dout5 = 0; + DBG("do5 OFF"); + } + else { + DBG("do5 OFF'ed"); + } + } + } + else { + if ((current_time_in_seconds >= do5OffTime) && ((current_time_in_seconds < do5OnTime))) { + if (dout5 == 1) { + dout5 = 0; + DBG("do5 OFF"); + } + else { + DBG("do5 OFF'ed"); + } + } + else { + if (dout5 == 0) { + dout5 = 1; + DBG("do5 ON"); + } + else { + DBG("do5 ON'ed"); + } + } + } + } // end check do5 + + // check do6 + if ((enable_onoff_dout && 0x40) == 0x40) { + if (do6OnTime < do6OffTime) { + if ((current_time_in_seconds >= do6OnTime) && (current_time_in_seconds < do6OffTime)){ + if (dout6 == 0) { + dout6 = 1; + DBG("do6 ON"); + } + else { + DBG("do6 ON'ed"); + } + } + else { + if (dout6 == 1) { + dout6 = 0; + DBG("do6 OFF"); + } + else { + DBG("do6 OFF'ed"); + } + } + } + else { + if ((current_time_in_seconds >= do6OffTime) && ((current_time_in_seconds < do6OnTime))) { + if (dout6 == 1) { + dout6 = 0; + DBG("do6 OFF"); + } + else { + DBG("do6 OFF'ed"); + } + } + else { + if (dout6 == 0) { + dout6 = 1; + DBG("do6 ON"); + } + else { + DBG("do6 ON'ed"); + } + } + } + } // end check do6 + + // check do7 + if ((enable_onoff_dout && 0x80) == 0x80) { + if (do7OnTime < do7OffTime) { + if ((current_time_in_seconds >= do7OnTime) && (current_time_in_seconds < do7OffTime)){ + if (dout7 == 0) { + dout7 = 1; + DBG("do7 ON"); + } + else { + DBG("do7 ON'ed"); + } + } + else { + if (dout7 == 1) { + dout7 = 0; + DBG("do7 OFF"); + } + else { + DBG("do7 OFF'ed"); + } + } + } + else { + if ((current_time_in_seconds >= do7OffTime) && ((current_time_in_seconds < do7OnTime))) { + if (dout7 == 1) { + dout7 = 0; + DBG("do7 OFF"); + } + else { + DBG("do7 OFF'ed"); + } + } + else { + if (dout7 == 0) { + dout7 = 1; + DBG("do7 ON"); + } + else { + DBG("do7 ON'ed"); + } + } + } + } // end check do7 + + + // wait 1s + Thread::wait(10000); // Thread::wait() in ms + } +} \ No newline at end of file