Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
