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

Committer:
olympux
Date:
Tue Jun 14 21:25:04 2016 +0000
Revision:
39:083cf93121a9
Parent:
38:f8735ae519aa
Child:
40:c966abbe2d62
New features; ; - Set current time; -  Set on/off time for DigitalOut 0 and 1; - Auto on/off do0, do1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
olympux 0:c2eac797face 1 /*
olympux 30:15e23257e786 2 * Firmware supports NNIO and RPC protocols
olympux 30:15e23257e786 3 */
olympux 0:c2eac797face 4 #include "mbed.h"
olympux 27:22f289beceb8 5 #include "rtos.h"
olympux 27:22f289beceb8 6 #include "mbed_rpc.h"
olympux 27:22f289beceb8 7 #include "Arguments.h"
olympux 27:22f289beceb8 8
olympux 12:7c152c0ca4d8 9 #include "eeprom.h"
olympux 0:c2eac797face 10 #include "EthernetInterface.h"
olympux 9:d2534ecf88c6 11 #include "NTPClient.h"
olympux 0:c2eac797face 12
olympux 12:7c152c0ca4d8 13 #include "my_eeprom_funcs.h"
olympux 20:71c7950fdd91 14 #include "Watchdog.h"
olympux 12:7c152c0ca4d8 15
olympux 0:c2eac797face 16
olympux 31:2e4b6de6c2f3 17 /** Debug option
olympux 31:2e4b6de6c2f3 18 *
olympux 31:2e4b6de6c2f3 19 */
olympux 25:48dd18cc147c 20 #if 1
olympux 16:84a5bf7285d0 21 //Enable debug
olympux 16:84a5bf7285d0 22 #include <cstdio>
olympux 31:2e4b6de6c2f3 23 #define DBG(x, ...) std::printf("[main : DBG]"x"\r\n", ##__VA_ARGS__);
olympux 31:2e4b6de6c2f3 24 #define WARN(x, ...) std::printf("[main : WARN]"x"\r\n", ##__VA_ARGS__);
olympux 31:2e4b6de6c2f3 25 #define ERR(x, ...) std::printf("[main : ERR]"x"\r\n", ##__VA_ARGS__);
olympux 16:84a5bf7285d0 26 #else
olympux 16:84a5bf7285d0 27 //Disable debug
olympux 31:2e4b6de6c2f3 28 #define DBG(x, ...)
olympux 16:84a5bf7285d0 29 #define WARN(x, ...)
olympux 31:2e4b6de6c2f3 30 #define ERR(x, ...)
olympux 16:84a5bf7285d0 31 #endif
olympux 16:84a5bf7285d0 32
olympux 16:84a5bf7285d0 33
olympux 2:18f10e7209f4 34 /*
olympux 2:18f10e7209f4 35 * Hardware defines
olympux 0:c2eac797face 36 */
olympux 9:d2534ecf88c6 37 // Ethernet
olympux 0:c2eac797face 38 SPI spi(PA_7, PA_6, PA_5); // mosi, miso, sclk
olympux 11:709f90a3b599 39 EthernetInterface eth(&spi, PA_4, PC_9); // spi, cs, reset
olympux 30:15e23257e786 40
olympux 30:15e23257e786 41 /*
olympux 30:15e23257e786 42 * EEPROM section
olympux 30:15e23257e786 43 */
olympux 30:15e23257e786 44 // Virtual address defined by the user: 0xFFFF value is prohibited
olympux 30:15e23257e786 45 uint16_t VirtAddVarTab[NumbOfVar] = {0x1212, 0x1313, 0x1414, 0x1515, // IP_Addr
olympux 30:15e23257e786 46 0x2212, 0x2313, 0x2414, 0x2515, // IP_Subnet
olympux 30:15e23257e786 47 0x3212, 0x3313, 0x3414, 0x3515, // IP_Gateway
olympux 30:15e23257e786 48 0x4212, // TCP server port, not used
olympux 30:15e23257e786 49 0x5212, // UDP server port, not used
olympux 30:15e23257e786 50 0x8888, // 1st run? 0xA5A5 = configured
olympux 30:15e23257e786 51 0x6212, 0x6313, 0x6414, // MAC
olympux 31:2e4b6de6c2f3 52
olympux 30:15e23257e786 53 // this section is for the TCP server that this device connects to in TCP client mode
olympux 30:15e23257e786 54 0x7212, 0x7313, // 0xA5A5 = auto transmit status, time period
olympux 30:15e23257e786 55 0x8212, 0x8313,0x8414, 0x8515, // TCP server IP address
olympux 30:15e23257e786 56 0x9212, // TCP server port
olympux 31:2e4b6de6c2f3 57
olympux 30:15e23257e786 58 // this section is for selecting protocol, not used
olympux 30:15e23257e786 59 0xA212, // 0xA5A5 = enable TCP server
olympux 30:15e23257e786 60 0xA313, // 0xA5A5 = eanble TCP client
olympux 30:15e23257e786 61 0xA414 // 0xA5A5 = enable UDP server
olympux 31:2e4b6de6c2f3 62 };
olympux 31:2e4b6de6c2f3 63
olympux 30:15e23257e786 64
olympux 30:15e23257e786 65 /*
olympux 30:15e23257e786 66 * Network configuration
olympux 30:15e23257e786 67 */
olympux 30:15e23257e786 68 #define TCP_SERVER
olympux 30:15e23257e786 69 #define TCP_CLIENT
olympux 30:15e23257e786 70 #define UDP_SERVER
olympux 30:15e23257e786 71 //#define UDP_CLIENT
olympux 30:15e23257e786 72 #define NTP
olympux 30:15e23257e786 73
olympux 30:15e23257e786 74 #define TCP_SERVER_WAIT_CLIENT_TIMEOUT 200 // timeout for local tcp server wait for a remote client
olympux 30:15e23257e786 75 #define TCP_SERVER_RECEIVE_TIMEOUT 2000 // timeout for local tcp server wait to receive from remote client
olympux 30:15e23257e786 76 #define TCP_CLIENT_RECEIVE_TIMEOUT 200 // timeout for local tcp client try to connect remote server
olympux 30:15e23257e786 77 #define UDP_SERVER_RECEIVE_TIMEOUT 100 // timeout for checking config command
olympux 30:15e23257e786 78
olympux 0:c2eac797face 79
olympux 30:15e23257e786 80 // TCP server function
olympux 30:15e23257e786 81 TCPSocketServer tcp_server;
olympux 30:15e23257e786 82 TCPSocketConnection tcp_client;
olympux 30:15e23257e786 83 // TCP client function
olympux 30:15e23257e786 84 TCPSocketConnection tcp_sock;
olympux 30:15e23257e786 85 // UDP server
olympux 30:15e23257e786 86 UDPSocket udp_server;
olympux 30:15e23257e786 87 Endpoint ep_udp_client;
olympux 30:15e23257e786 88 // NTP
olympux 30:15e23257e786 89 NTPClient ntp;
olympux 30:15e23257e786 90
olympux 30:15e23257e786 91
olympux 30:15e23257e786 92 /*
olympux 30:15e23257e786 93 * Variables for network configuration, TCP server
olympux 30:15e23257e786 94 */
olympux 30:15e23257e786 95 uint8_t u8mac[6], u8ip_addr[4];// keep mac and ip address in 8-bits
olympux 30:15e23257e786 96 uint16_t u16mac_addr[3], u16ip_addr[4], u16ip_subnet[4], u16ip_gateway[4]; // 16-bits, directly loaded from eeprom
olympux 30:15e23257e786 97 char str_ip_addr[16], str_ip_subnet[16], str_ip_gateway[16]; // for printf, converted from 16-bits u16ip_xxx
olympux 30:15e23257e786 98 uint16_t configured_ip = 0; // static ip configured flag
olympux 30:15e23257e786 99
olympux 30:15e23257e786 100 const uint16_t tcp_server_local_port = 10000; // fixed, change to 7000 if internet required
olympux 30:15e23257e786 101 const uint16_t udp_server_local_port = 11000; // fixed
olympux 30:15e23257e786 102
olympux 30:15e23257e786 103 // TCP client: this section is used for the TCP server that this device connects to in TCP client mode
olympux 30:15e23257e786 104 // this device will transmit status every transmit_time_period
olympux 30:15e23257e786 105 uint16_t auto_transmit_flag = 0, transmit_time_period = 1000; // auto transmit status, time period = 1s
olympux 30:15e23257e786 106 uint16_t u16server_ip_addr[4]; // directly loaded from eeprom
olympux 30:15e23257e786 107 uint8_t u8server_ip_addr[4]; // server ip address in 8-bits
olympux 30:15e23257e786 108 char str_server_ip_addr[16];// for printf, converted from 16-bits u16server_ip_addr
olympux 30:15e23257e786 109 uint16_t u16tcp_server_port; // directly loaded from eeprom
olympux 30:15e23257e786 110 uint16_t u16enable_tcp_client, u16enable_tcp_server;// flags for enabling TCP client or TCP server
olympux 30:15e23257e786 111
olympux 30:15e23257e786 112 #define NET_BUF_LEN 256
olympux 30:15e23257e786 113 char tcp_receiving_buffer[NET_BUF_LEN];
olympux 30:15e23257e786 114 char udp_receiving_buffer[NET_BUF_LEN];
olympux 31:2e4b6de6c2f3 115 char network_output_buffer[NET_BUF_LEN]; // output buffer for TCP/UDP control command
olympux 30:15e23257e786 116
olympux 30:15e23257e786 117
olympux 30:15e23257e786 118 /*
olympux 30:15e23257e786 119 * RPC Protocol
olympux 30:15e23257e786 120 * Use the RPC enabled wrapped class - see RpcClasses.h for more info
olympux 30:15e23257e786 121 */
olympux 27:22f289beceb8 122 // DigitalIn
olympux 35:f5c98e2d6aad 123 RpcDigitalIn di0(PB_14, "di0");
olympux 35:f5c98e2d6aad 124 RpcDigitalIn di1(PB_12, "di1");
olympux 35:f5c98e2d6aad 125 RpcDigitalIn di2(PB_10, "di2");
olympux 35:f5c98e2d6aad 126 RpcDigitalIn di3(PB_1, "di3");
olympux 35:f5c98e2d6aad 127 RpcDigitalIn di4(PB_15, "di4");
olympux 35:f5c98e2d6aad 128 RpcDigitalIn di5(PB_13, "di5");
olympux 35:f5c98e2d6aad 129 RpcDigitalIn di6(PB_11, "di6");
olympux 35:f5c98e2d6aad 130 RpcDigitalIn di7(PB_2, "di7");
olympux 11:709f90a3b599 131 DigitalIn din0(PB_14);
olympux 11:709f90a3b599 132 DigitalIn din1(PB_12);
olympux 11:709f90a3b599 133 DigitalIn din2(PB_10);
olympux 11:709f90a3b599 134 DigitalIn din3(PB_1);
olympux 11:709f90a3b599 135 DigitalIn din4(PB_15);
olympux 11:709f90a3b599 136 DigitalIn din5(PB_13);
olympux 11:709f90a3b599 137 DigitalIn din6(PB_11);
olympux 11:709f90a3b599 138 DigitalIn din7(PB_2);
olympux 27:22f289beceb8 139 // DigitalOut
olympux 35:f5c98e2d6aad 140 RpcDigitalOut do0(PB_3, "do0");
olympux 35:f5c98e2d6aad 141 RpcDigitalOut do1(PB_5, "do1");
olympux 35:f5c98e2d6aad 142 RpcDigitalOut do2(PB_7, "do2");
olympux 35:f5c98e2d6aad 143 RpcDigitalOut do3(PB_9, "do3");
olympux 35:f5c98e2d6aad 144 RpcDigitalOut do4(PD_2, "do4");
olympux 35:f5c98e2d6aad 145 RpcDigitalOut do5(PB_4, "do5");
olympux 35:f5c98e2d6aad 146 RpcDigitalOut do6(PB_6, "do6");
olympux 35:f5c98e2d6aad 147 RpcDigitalOut do7(PB_8, "do7");
olympux 11:709f90a3b599 148 DigitalOut dout0(PB_3);
olympux 11:709f90a3b599 149 DigitalOut dout1(PB_5);
olympux 11:709f90a3b599 150 DigitalOut dout2(PB_7);
olympux 11:709f90a3b599 151 DigitalOut dout3(PB_9);
olympux 11:709f90a3b599 152 DigitalOut dout4(PD_2);
olympux 11:709f90a3b599 153 DigitalOut dout5(PB_4);
olympux 11:709f90a3b599 154 DigitalOut dout6(PB_6);
olympux 11:709f90a3b599 155 DigitalOut dout7(PB_8);
olympux 27:22f289beceb8 156 // AnalogIn
olympux 35:f5c98e2d6aad 157 RpcAnalogIn adc10(PC_0, "ai0"); // adc10
olympux 35:f5c98e2d6aad 158 RpcAnalogIn adc11(PC_1, "ai1"); // adc11
olympux 11:709f90a3b599 159 AnalogIn ain0(PC_0);
olympux 11:709f90a3b599 160 AnalogIn ain1(PC_1);
olympux 27:22f289beceb8 161 // AnalogOut, PWM
olympux 27:22f289beceb8 162 RpcPwmOut pwm11(PA_8, "pwm0"); // pwm11
olympux 27:22f289beceb8 163 RpcPwmOut pwm21(PA_15, "pwm1"); // pwm21
olympux 27:22f289beceb8 164 // Serial
olympux 27:22f289beceb8 165 RpcSerial usart2(USBTX, USBRX, "uart"); // usart2
olympux 27:22f289beceb8 166 Serial uart(USBTX,USBRX);
olympux 27:22f289beceb8 167 // Timer
olympux 35:f5c98e2d6aad 168 RpcTimer timer1("tmr1");
olympux 20:71c7950fdd91 169 // Watchdog
olympux 20:71c7950fdd91 170 Watchdog wdt;
olympux 20:71c7950fdd91 171
olympux 39:083cf93121a9 172
olympux 39:083cf93121a9 173 // Some variable types that can be modified through RPC.
olympux 39:083cf93121a9 174 //int wheelsOn;
olympux 39:083cf93121a9 175 //char lcdBannerMessage;
olympux 39:083cf93121a9 176 //float speed;
olympux 39:083cf93121a9 177 int current_time;
olympux 39:083cf93121a9 178 int do0OnTime, do0OffTime;
olympux 39:083cf93121a9 179 int do1OnTime, do1OffTime;
olympux 39:083cf93121a9 180
olympux 39:083cf93121a9 181 //RPCVariable<int> rpcLights(&wheelsOn, "wheels");
olympux 39:083cf93121a9 182 //RPCVariable<char> rpcBanner(&lcdBannerMessage, "banner");
olympux 39:083cf93121a9 183 //RPCVariable<float> rpcSpeed(&speed, "speed");
olympux 39:083cf93121a9 184 RPCVariable<int> rpcCurrentTime(&current_time, "Time");
olympux 39:083cf93121a9 185 RPCVariable<int> rpcdo0OnTime(&do0OnTime, "do0OnTime");
olympux 39:083cf93121a9 186 RPCVariable<int> rpcdo0OffTime(&do0OffTime, "do0OffTime");
olympux 39:083cf93121a9 187 RPCVariable<int> rpcdo1OnTime(&do0OnTime, "do1OnTime");
olympux 39:083cf93121a9 188 RPCVariable<int> rpcdo1OffTime(&do0OffTime, "do1OffTime");
olympux 39:083cf93121a9 189
olympux 39:083cf93121a9 190 // RPC function definitions
olympux 39:083cf93121a9 191 // Create a function of the required format
olympux 39:083cf93121a9 192 void set_current_time(Arguments* args, Reply* rep);
olympux 39:083cf93121a9 193 void set_current_time(Arguments* args, Reply* rep){
olympux 39:083cf93121a9 194 time_t ct = (time_t)current_time; // convert
olympux 39:083cf93121a9 195 struct tm *st = localtime(&ct);
olympux 39:083cf93121a9 196
olympux 39:083cf93121a9 197 set_time(ct); // set time
olympux 39:083cf93121a9 198
olympux 39:083cf93121a9 199 DBG("Set current time to: %s", ctime(&ct));
olympux 39:083cf93121a9 200 DBG("Time only: %d:%d:%d", st->tm_hour, st->tm_min, st->tm_sec);
olympux 39:083cf93121a9 201 }
olympux 39:083cf93121a9 202 // Attach it to an RPC object
olympux 39:083cf93121a9 203 RPCFunction rpcSetCurrentTime(&set_current_time, "SetTime");
olympux 39:083cf93121a9 204
olympux 13:bcf840da68fd 205 /*
olympux 30:15e23257e786 206 * NNIO Protocol
olympux 30:15e23257e786 207 */
olympux 9:d2534ecf88c6 208 // Commands
olympux 29:bc052f283ada 209 #define DEVICE_DESCRIPTION "NNIO"
olympux 27:22f289beceb8 210 #define DEVICE_CONFIG_CODE "NNCF"
olympux 27:22f289beceb8 211 #define DEVICE_CONTROL_CODE "NNIO"
olympux 17:88ef7a078095 212
olympux 17:88ef7a078095 213 #define RECEIVING_PROTOCOL_LENGTH 58
olympux 17:88ef7a078095 214 #define SENDING_PROTOCOL_LENGTH 39
olympux 26:09e0dd020900 215 #define QUERY_NETWORK_CONFIG_CMD_LENGTH 6
olympux 17:88ef7a078095 216 #define SET_NETWORK_CONFIG_CMD_LENGTH 19
olympux 26:09e0dd020900 217 #define UPDATE_TCP_SERVER_INFO_COMMAND_LENGTH 12
olympux 17:88ef7a078095 218
olympux 27:22f289beceb8 219 #define QUERY_DISCOVERY_CMD "NNCFDS"
olympux 27:22f289beceb8 220 #define QUERY_IP_CMD "NNCFIP"
olympux 27:22f289beceb8 221 #define QUERY_SUBNET_CMD "NNCFSN"
olympux 27:22f289beceb8 222 #define QUERY_GATEWAY_CMD "NNCFGW"
olympux 27:22f289beceb8 223 #define QUERY_MAC_CMD "NNCFMC"
olympux 27:22f289beceb8 224 #define QUERY_UDP_PORT_CMD "NNCFUP"
olympux 27:22f289beceb8 225 #define QUERY_TCP_PORT_CMD "NNCFTP"
olympux 27:22f289beceb8 226 #define QUERY_UPDATE_TIME_CMD "NNCFTM"
olympux 11:709f90a3b599 227 #define RECEIVING_PROTOCOL_ENABLE_OUTPUT 'O'
olympux 11:709f90a3b599 228 #define QUERY_STATUS_COMMAND 'Q'
olympux 11:709f90a3b599 229 #define DIGITAL_HIGH 'H'
olympux 11:709f90a3b599 230 #define DIGITAL_LOW 'L'
olympux 9:d2534ecf88c6 231
olympux 9:d2534ecf88c6 232
olympux 9:d2534ecf88c6 233 // Positions
olympux 11:709f90a3b599 234 #define RECEIVING_PROTOCOL_ID_POS 0
olympux 9:d2534ecf88c6 235 #define RECEIVING_PROTOCOL_OP_POS 4
olympux 9:d2534ecf88c6 236 #define RECEIVING_PROTOCOL_EN_DO_POS RECEIVING_PROTOCOL_OP_POS + 0
olympux 9:d2534ecf88c6 237 #define RECEIVING_PROTOCOL_EN_A0O_POS RECEIVING_PROTOCOL_OP_POS + 1
olympux 9:d2534ecf88c6 238 #define RECEIVING_PROTOCOL_EN_A1O_POS RECEIVING_PROTOCOL_OP_POS + 2
olympux 9:d2534ecf88c6 239 #define RECEIVING_PROTOCOL_EN_UART_POS RECEIVING_PROTOCOL_OP_POS + 3
olympux 9:d2534ecf88c6 240 #define RECEIVING_PROTOCOL_COMMAND_POS RECEIVING_PROTOCOL_OP_POS + 4
olympux 11:709f90a3b599 241
olympux 11:709f90a3b599 242 #define RECEIVING_PROTOCOL_IP_POS 9
olympux 11:709f90a3b599 243 #define RECEIVING_PROTOCOL_DO_POS 13
olympux 11:709f90a3b599 244 #define RECEIVING_PROTOCOL_A0O_POS 21
olympux 11:709f90a3b599 245 #define RECEIVING_PROTOCOL_A01_POS 23
olympux 11:709f90a3b599 246 #define RECEIVING_PROTOCOL_UART_POS 25
olympux 9:d2534ecf88c6 247
olympux 9:d2534ecf88c6 248
olympux 11:709f90a3b599 249 #define SENDING_PROTOCOL_ID_POS 0
olympux 11:709f90a3b599 250 #define SENDING_PROTOCOL_MAC_POS 4
olympux 11:709f90a3b599 251 #define SENDING_PROTOCOL_IP_POS 10
olympux 11:709f90a3b599 252 #define SENDING_PROTOCOL_DI_POS 14
olympux 11:709f90a3b599 253 #define SENDING_PROTOCOL_DO_POS 22
olympux 11:709f90a3b599 254 #define SENDING_PROTOCOL_AI0_POS 30
olympux 11:709f90a3b599 255 #define SENDING_PROTOCOL_AI1_POS 32
olympux 11:709f90a3b599 256 #define SENDING_PROTOCOL_AO0_POS 34
olympux 11:709f90a3b599 257 #define SENDING_PROTOCOL_AO1_POS 36
olympux 11:709f90a3b599 258 #define SENDING_PROTOCOL_CR_POS 38
olympux 0:c2eac797face 259
olympux 2:18f10e7209f4 260
olympux 2:18f10e7209f4 261 /*
olympux 2:18f10e7209f4 262 * RTOS
olympux 2:18f10e7209f4 263 */
olympux 2:18f10e7209f4 264 struct message_t {
olympux 2:18f10e7209f4 265 int len;
olympux 2:18f10e7209f4 266 char *msg;
olympux 2:18f10e7209f4 267 };
olympux 3:972ed747474c 268 Queue<message_t, 16> uart_queue;
olympux 15:edeb0aed160d 269 Queue<bool, 1> auto_update_queue;
olympux 2:18f10e7209f4 270
olympux 2:18f10e7209f4 271
olympux 26:09e0dd020900 272
olympux 26:09e0dd020900 273 // Prototypes
olympux 26:09e0dd020900 274 int ethernet_init(void);
olympux 28:00c0c20d03c1 275 int process_control_command(char* received_buffer, int len);
olympux 26:09e0dd020900 276 void process_config_command(char* received_buffer, int len);
olympux 26:09e0dd020900 277 void update_digital_outputs(char* buf);
olympux 26:09e0dd020900 278 void update_sending_frame(char* buf);
olympux 26:09e0dd020900 279
olympux 26:09e0dd020900 280
olympux 2:18f10e7209f4 281 /*
olympux 2:18f10e7209f4 282 * Threads
olympux 2:18f10e7209f4 283 */
olympux 31:2e4b6de6c2f3 284 // Timer thread for auto update in TCP client function
olympux 31:2e4b6de6c2f3 285 void auto_update_timer_thread(void const* args)
olympux 31:2e4b6de6c2f3 286 {
olympux 18:ca499a2e7da6 287 bool update_flag = true;
olympux 31:2e4b6de6c2f3 288
olympux 15:edeb0aed160d 289 Thread::wait(500);
olympux 15:edeb0aed160d 290 while(true) {
olympux 15:edeb0aed160d 291 auto_update_queue.put(&update_flag);
olympux 18:ca499a2e7da6 292 Thread::wait(1000*transmit_time_period); // Thread::wait() in ms
olympux 15:edeb0aed160d 293 }
olympux 15:edeb0aed160d 294 }
olympux 15:edeb0aed160d 295
olympux 15:edeb0aed160d 296
olympux 20:71c7950fdd91 297 // WDT reset
olympux 31:2e4b6de6c2f3 298 void wdt_reset_thread(void const* args)
olympux 31:2e4b6de6c2f3 299 {
olympux 20:71c7950fdd91 300 while (true)
olympux 20:71c7950fdd91 301 wdt.Service();
olympux 20:71c7950fdd91 302 }
olympux 20:71c7950fdd91 303
olympux 39:083cf93121a9 304 // Timer thread to check on/off time
olympux 39:083cf93121a9 305 void digital_outputs_timer_thread(void const* args)
olympux 39:083cf93121a9 306 {
olympux 39:083cf93121a9 307 Thread::wait(700);
olympux 39:083cf93121a9 308
olympux 39:083cf93121a9 309 while(true) {
olympux 39:083cf93121a9 310 // read current time
olympux 39:083cf93121a9 311 time_t seconds = time(NULL);
olympux 39:083cf93121a9 312 struct tm *st = localtime(&seconds);
olympux 39:083cf93121a9 313 int current_time_in_seconds = 3600*(st->tm_hour) + 60*(st->tm_min) + st->tm_sec;
olympux 39:083cf93121a9 314 DBG("Current time: %d:%d:%d", st->tm_hour, st->tm_min, st->tm_sec);
olympux 39:083cf93121a9 315
olympux 39:083cf93121a9 316 // check do0
olympux 39:083cf93121a9 317 if (do0OnTime < do0OffTime) {
olympux 39:083cf93121a9 318 if ((current_time_in_seconds >= do0OnTime) && (current_time_in_seconds < do0OffTime)){
olympux 39:083cf93121a9 319 if (dout0 == 0) {
olympux 39:083cf93121a9 320 dout0 = 1;
olympux 39:083cf93121a9 321 DBG("do0 ON");
olympux 39:083cf93121a9 322 }
olympux 39:083cf93121a9 323 else {
olympux 39:083cf93121a9 324 DBG("do0 ON'ed");
olympux 39:083cf93121a9 325 }
olympux 39:083cf93121a9 326 }
olympux 39:083cf93121a9 327 else {
olympux 39:083cf93121a9 328 if (dout0 == 1) {
olympux 39:083cf93121a9 329 dout0 = 0;
olympux 39:083cf93121a9 330 DBG("do0 OFF'ed");
olympux 39:083cf93121a9 331 }
olympux 39:083cf93121a9 332 else {
olympux 39:083cf93121a9 333 DBG("do0 OFF");
olympux 39:083cf93121a9 334 }
olympux 39:083cf93121a9 335 }
olympux 39:083cf93121a9 336 }
olympux 39:083cf93121a9 337 else {
olympux 39:083cf93121a9 338 if ((current_time_in_seconds >= do0OffTime) && ((current_time_in_seconds < do0OnTime))) {
olympux 39:083cf93121a9 339 if (dout0 == 1) {
olympux 39:083cf93121a9 340 dout0 = 0;
olympux 39:083cf93121a9 341 DBG("do0 OFF");
olympux 39:083cf93121a9 342 }
olympux 39:083cf93121a9 343 else {
olympux 39:083cf93121a9 344 DBG("do0 OFF'ed");
olympux 39:083cf93121a9 345 }
olympux 39:083cf93121a9 346 }
olympux 39:083cf93121a9 347 else {
olympux 39:083cf93121a9 348 if (dout0 == 0) {
olympux 39:083cf93121a9 349 dout0 = 1;
olympux 39:083cf93121a9 350 DBG("do0 ON");
olympux 39:083cf93121a9 351 }
olympux 39:083cf93121a9 352 else {
olympux 39:083cf93121a9 353 DBG("do0 ON'ed");
olympux 39:083cf93121a9 354 }
olympux 39:083cf93121a9 355 }
olympux 39:083cf93121a9 356 }
olympux 39:083cf93121a9 357
olympux 39:083cf93121a9 358 // check do1
olympux 39:083cf93121a9 359 if (do1OnTime < do1OffTime) {
olympux 39:083cf93121a9 360 if ((current_time_in_seconds >= do1OnTime) && (current_time_in_seconds < do1OffTime)){
olympux 39:083cf93121a9 361 if (dout1 == 0) {
olympux 39:083cf93121a9 362 dout1 = 1;
olympux 39:083cf93121a9 363 DBG("do1 ON");
olympux 39:083cf93121a9 364 }
olympux 39:083cf93121a9 365 else {
olympux 39:083cf93121a9 366 DBG("do1 ON'ed");
olympux 39:083cf93121a9 367 }
olympux 39:083cf93121a9 368 }
olympux 39:083cf93121a9 369 else {
olympux 39:083cf93121a9 370 if (dout1 == 1) {
olympux 39:083cf93121a9 371 dout1 = 0;
olympux 39:083cf93121a9 372 DBG("do1 OFF");
olympux 39:083cf93121a9 373 }
olympux 39:083cf93121a9 374 else {
olympux 39:083cf93121a9 375 DBG("do1 OFF'ed");
olympux 39:083cf93121a9 376 }
olympux 39:083cf93121a9 377 }
olympux 39:083cf93121a9 378 }
olympux 39:083cf93121a9 379 else {
olympux 39:083cf93121a9 380 if ((current_time_in_seconds >= do1OffTime) && ((current_time_in_seconds < do1OnTime))) {
olympux 39:083cf93121a9 381 if (dout1 == 1) {
olympux 39:083cf93121a9 382 dout1 = 0;
olympux 39:083cf93121a9 383 DBG("do1 OFF");
olympux 39:083cf93121a9 384 }
olympux 39:083cf93121a9 385 else {
olympux 39:083cf93121a9 386 DBG("do1 OFF'ed");
olympux 39:083cf93121a9 387 }
olympux 39:083cf93121a9 388 }
olympux 39:083cf93121a9 389 else {
olympux 39:083cf93121a9 390 if (dout1 == 0) {
olympux 39:083cf93121a9 391 dout1 = 1;
olympux 39:083cf93121a9 392 DBG("do1 ON");
olympux 39:083cf93121a9 393 }
olympux 39:083cf93121a9 394 else {
olympux 39:083cf93121a9 395 DBG("do1 ON'ed");
olympux 39:083cf93121a9 396 }
olympux 39:083cf93121a9 397 }
olympux 39:083cf93121a9 398 }
olympux 39:083cf93121a9 399 // wait 1s
olympux 39:083cf93121a9 400 Thread::wait(10000); // Thread::wait() in ms
olympux 39:083cf93121a9 401 }
olympux 38:f8735ae519aa 402 }
olympux 38:f8735ae519aa 403
olympux 38:f8735ae519aa 404 // Main code
olympux 4:568c97f2a407 405 int main()
olympux 4:568c97f2a407 406 {
olympux 9:d2534ecf88c6 407 int n, ret;
olympux 31:2e4b6de6c2f3 408
olympux 20:71c7950fdd91 409 Thread::wait(500); // turn on delay
olympux 31:2e4b6de6c2f3 410
olympux 4:568c97f2a407 411 /*
olympux 9:d2534ecf88c6 412 * Configure
olympux 4:568c97f2a407 413 */
olympux 11:709f90a3b599 414 uart.baud(115200);
olympux 36:dc6f079777bb 415 DBG("Starting...");
olympux 31:2e4b6de6c2f3 416
olympux 31:2e4b6de6c2f3 417 // check watchdog
olympux 20:71c7950fdd91 418 if (wdt.WatchdogCausedReset())
olympux 20:71c7950fdd91 419 DBG("Watchdog caused reset.");
olympux 20:71c7950fdd91 420 wdt.Configure(4);
olympux 31:2e4b6de6c2f3 421
olympux 6:d054e394fba3 422 /*
olympux 6:d054e394fba3 423 * FLASH
olympux 6:d054e394fba3 424 */
olympux 12:7c152c0ca4d8 425 load_eeprom_network();
olympux 15:edeb0aed160d 426 load_eeprom_tcpserver();
olympux 31:2e4b6de6c2f3 427
olympux 20:71c7950fdd91 428 /*
olympux 20:71c7950fdd91 429 * UI threads
olympux 20:71c7950fdd91 430 */
olympux 33:c906ccc220ba 431 Thread t2(auto_update_timer_thread);
olympux 20:71c7950fdd91 432 Thread t3(wdt_reset_thread);
olympux 39:083cf93121a9 433 Thread t4(digital_outputs_timer_thread);
olympux 31:2e4b6de6c2f3 434
olympux 4:568c97f2a407 435 /*
olympux 4:568c97f2a407 436 * Ethernet
olympux 4:568c97f2a407 437 */
olympux 6:d054e394fba3 438 ret = ethernet_init();
olympux 4:568c97f2a407 439 if (ret) {
olympux 18:ca499a2e7da6 440 ERR("Ethernet initialisation failed. App halted.");
olympux 4:568c97f2a407 441 while (true) {};
olympux 4:568c97f2a407 442 }
olympux 31:2e4b6de6c2f3 443
olympux 23:47ee805435b1 444 Thread::wait(2000); // TCP/UDP stack delay
olympux 12:7c152c0ca4d8 445
olympux 31:2e4b6de6c2f3 446 /*
olympux 31:2e4b6de6c2f3 447 * UDP server
olympux 31:2e4b6de6c2f3 448 * TCP server/client
olympux 31:2e4b6de6c2f3 449 */
olympux 20:71c7950fdd91 450 #ifdef UDP_SERVER
olympux 20:71c7950fdd91 451 ret = udp_server.bind(udp_server_local_port);
olympux 20:71c7950fdd91 452 DBG("UDP server started (sock.bind = %d)...", ret);
olympux 20:71c7950fdd91 453 udp_server.set_blocking(false, UDP_SERVER_RECEIVE_TIMEOUT);
olympux 20:71c7950fdd91 454 #endif
olympux 20:71c7950fdd91 455
olympux 3:972ed747474c 456 #ifdef TCP_SERVER
olympux 12:7c152c0ca4d8 457 tcp_server.bind(tcp_server_local_port);
olympux 3:972ed747474c 458 tcp_server.listen();
olympux 18:ca499a2e7da6 459 DBG("TCP server started...");
olympux 4:568c97f2a407 460 tcp_server.set_blocking(false, TCP_SERVER_WAIT_CLIENT_TIMEOUT);
olympux 3:972ed747474c 461 #endif
olympux 14:18eda020a589 462
olympux 14:18eda020a589 463 #ifdef TCP_CLIENT
olympux 18:ca499a2e7da6 464
olympux 14:18eda020a589 465 #endif
olympux 31:2e4b6de6c2f3 466
olympux 12:7c152c0ca4d8 467 /*
olympux 19:05934ee9ee67 468 * Network loop processor
olympux 12:7c152c0ca4d8 469 */
olympux 0:c2eac797face 470 while (true) {
olympux 30:15e23257e786 471 #ifdef TCP_CLIENT // auto update device status to a remote TCP server
olympux 33:c906ccc220ba 472 if (auto_transmit_flag == DEFAULT_ENABLE_FLAG_VALUE) {
olympux 18:ca499a2e7da6 473 // connect to TCP server if required
olympux 18:ca499a2e7da6 474 if (!tcp_sock.is_connected()) {
olympux 20:71c7950fdd91 475 ret = tcp_sock.connect(str_server_ip_addr, u16tcp_server_port); // timeout is default in connect() in W5500.h
olympux 18:ca499a2e7da6 476 if (ret > -1) {
olympux 18:ca499a2e7da6 477 DBG("Successfully connected to %s on port %d", str_server_ip_addr, u16tcp_server_port);
olympux 31:2e4b6de6c2f3 478 } else {
olympux 18:ca499a2e7da6 479 ERR("Unable to connect to %s on port %d", str_server_ip_addr, u16tcp_server_port);
olympux 18:ca499a2e7da6 480 }
olympux 16:84a5bf7285d0 481 }
olympux 31:2e4b6de6c2f3 482
olympux 18:ca499a2e7da6 483 // transmit data if connected
olympux 18:ca499a2e7da6 484 if (tcp_sock.is_connected()) {
olympux 18:ca499a2e7da6 485 osEvent evt = auto_update_queue.get(1); // timeout after 1ms
olympux 18:ca499a2e7da6 486 if (evt.status == osEventMessage) {
olympux 18:ca499a2e7da6 487 DBG("Updating...");
olympux 31:2e4b6de6c2f3 488 update_sending_frame(network_output_buffer);
olympux 31:2e4b6de6c2f3 489 tcp_sock.send_all(network_output_buffer, SENDING_PROTOCOL_LENGTH);
olympux 19:05934ee9ee67 490 }
olympux 31:2e4b6de6c2f3 491
olympux 19:05934ee9ee67 492 // check to receive or timeout
olympux 19:05934ee9ee67 493 tcp_sock.set_blocking(false, TCP_CLIENT_RECEIVE_TIMEOUT);
olympux 19:05934ee9ee67 494 n = tcp_sock.receive(tcp_receiving_buffer, sizeof(tcp_receiving_buffer));
olympux 19:05934ee9ee67 495 if (n > 0) {
olympux 19:05934ee9ee67 496 // got some data, test it
olympux 19:05934ee9ee67 497 DBG("TCP client received %d bytes: %s", n, tcp_receiving_buffer);
olympux 32:db2e8ea06ee1 498 n = process_control_command(tcp_receiving_buffer, n);
olympux 32:db2e8ea06ee1 499 // send reply back to client, NNIO protocol always returns 0
olympux 32:db2e8ea06ee1 500 // RPC-style protocol
olympux 32:db2e8ea06ee1 501 if (n > 0) {
olympux 32:db2e8ea06ee1 502 network_output_buffer[n] = '\0';
olympux 32:db2e8ea06ee1 503 tcp_sock.send_all(network_output_buffer, strlen(network_output_buffer));
olympux 32:db2e8ea06ee1 504 } // RPC-style protocol
olympux 32:db2e8ea06ee1 505 else if (n == 0) {
olympux 32:db2e8ea06ee1 506 // then, check query status command and sending protocol if required
olympux 32:db2e8ea06ee1 507 if (tcp_receiving_buffer[RECEIVING_PROTOCOL_COMMAND_POS] == QUERY_STATUS_COMMAND) {
olympux 32:db2e8ea06ee1 508 DBG("Requested to send device status through TCP");
olympux 32:db2e8ea06ee1 509 // sending protocol
olympux 32:db2e8ea06ee1 510 update_sending_frame(network_output_buffer);
olympux 32:db2e8ea06ee1 511 tcp_sock.send_all(network_output_buffer, SENDING_PROTOCOL_LENGTH);
olympux 32:db2e8ea06ee1 512 DBG("Sent");
olympux 32:db2e8ea06ee1 513 }
olympux 32:db2e8ea06ee1 514 } // NNIO protocol
olympux 18:ca499a2e7da6 515 }
olympux 16:84a5bf7285d0 516 }
olympux 18:ca499a2e7da6 517 } // if tcp client enabled && auto transmit
olympux 15:edeb0aed160d 518 #endif
olympux 15:edeb0aed160d 519
olympux 15:edeb0aed160d 520
olympux 30:15e23257e786 521 #ifdef TCP_SERVER // control and monitor from a remote TCP client, both NNIO and RPC-style
olympux 30:15e23257e786 522 // no tcp client connected{
olympux 20:71c7950fdd91 523 if (1) {
olympux 4:568c97f2a407 524 // wait for client within timeout
olympux 4:568c97f2a407 525 ret = tcp_server.accept(tcp_client);
olympux 31:2e4b6de6c2f3 526
olympux 4:568c97f2a407 527 // tcp client connected
olympux 4:568c97f2a407 528 if (ret > -1) {
olympux 18:ca499a2e7da6 529 DBG("Connection from: %s", tcp_client.get_address());
olympux 31:2e4b6de6c2f3 530
olympux 4:568c97f2a407 531 // loop waiting and receiving data within timeout
olympux 4:568c97f2a407 532 tcp_client.set_blocking(false, TCP_SERVER_RECEIVE_TIMEOUT); // Timeout after x seconds
olympux 31:2e4b6de6c2f3 533 while (tcp_client.is_connected()) {
olympux 19:05934ee9ee67 534 n = tcp_client.receive(tcp_receiving_buffer, sizeof(tcp_receiving_buffer));
olympux 4:568c97f2a407 535 if (n <= 0) break;
olympux 31:2e4b6de6c2f3 536
olympux 28:00c0c20d03c1 537 // got some data, process it
olympux 27:22f289beceb8 538 tcp_receiving_buffer[n] = '\0'; // for debugging purpose
olympux 19:05934ee9ee67 539 DBG("TCP server received: %s", tcp_receiving_buffer);
olympux 28:00c0c20d03c1 540 n = process_control_command(tcp_receiving_buffer, n);
olympux 31:2e4b6de6c2f3 541 // send reply back to client, NNIO protocol always returns 0
olympux 31:2e4b6de6c2f3 542 // RPC-style protocol
olympux 28:00c0c20d03c1 543 if (n > 0) {
olympux 31:2e4b6de6c2f3 544 network_output_buffer[n] = '\0';
olympux 31:2e4b6de6c2f3 545 tcp_client.send_all(network_output_buffer, strlen(network_output_buffer));
olympux 31:2e4b6de6c2f3 546 } // RPC-style protocol
olympux 31:2e4b6de6c2f3 547 else if (n == 0) {
olympux 31:2e4b6de6c2f3 548 // then, check query status command and sending protocol if required
olympux 31:2e4b6de6c2f3 549 if (tcp_receiving_buffer[RECEIVING_PROTOCOL_COMMAND_POS] == QUERY_STATUS_COMMAND) {
olympux 31:2e4b6de6c2f3 550 DBG("Requested to send device status through TCP");
olympux 31:2e4b6de6c2f3 551 // sending protocol
olympux 31:2e4b6de6c2f3 552 update_sending_frame(network_output_buffer);
olympux 31:2e4b6de6c2f3 553 tcp_client.send_all(network_output_buffer, SENDING_PROTOCOL_LENGTH);
olympux 31:2e4b6de6c2f3 554 DBG("Sent");
olympux 31:2e4b6de6c2f3 555 }
olympux 31:2e4b6de6c2f3 556 } // NNIO protocol
olympux 4:568c97f2a407 557 } // end loop if no data received within timeout
olympux 4:568c97f2a407 558 } // if client connected
olympux 20:71c7950fdd91 559 tcp_client.close();
olympux 18:ca499a2e7da6 560 } // if tcp server enabled && no client connected
olympux 3:972ed747474c 561 #endif
olympux 20:71c7950fdd91 562
olympux 30:15e23257e786 563 #ifdef UDP_SERVER // configuration and control, both NNIO and RPC-style
olympux 27:22f289beceb8 564 bool discovery_mode_flag, config_mode_flag;
olympux 31:2e4b6de6c2f3 565
olympux 19:05934ee9ee67 566 n = udp_server.receiveFrom(ep_udp_client, udp_receiving_buffer, sizeof(udp_receiving_buffer));
olympux 31:2e4b6de6c2f3 567
olympux 25:48dd18cc147c 568 // check to see if it is a query command
olympux 25:48dd18cc147c 569 // if yes, is it a discovery command or an ip query to enter config mode
olympux 27:22f289beceb8 570 discovery_mode_flag = false;
olympux 25:48dd18cc147c 571 config_mode_flag = false;
olympux 26:09e0dd020900 572 if ((n == QUERY_NETWORK_CONFIG_CMD_LENGTH) && (strstr(udp_receiving_buffer, QUERY_DISCOVERY_CMD) != NULL)) {
olympux 27:22f289beceb8 573 discovery_mode_flag = true;
olympux 25:48dd18cc147c 574 DBG("Received discovery command");
olympux 25:48dd18cc147c 575 char str[50];
olympux 29:bc052f283ada 576 sprintf(str, "%s%s%s", DEVICE_DESCRIPTION, eth.getMACAddress(), eth.getIPAddress());
olympux 25:48dd18cc147c 577 udp_server.sendTo(ep_udp_client, str, strlen(str));
olympux 27:22f289beceb8 578 } // NNCFDS
olympux 26:09e0dd020900 579 else if ((n == QUERY_NETWORK_CONFIG_CMD_LENGTH) && (strstr(udp_receiving_buffer, QUERY_IP_CMD) != NULL)) {
olympux 25:48dd18cc147c 580 config_mode_flag = true;
olympux 27:22f289beceb8 581 DBG("Entered configuration mode...");
olympux 20:71c7950fdd91 582 DBG("!!! RESET when finished");
olympux 27:22f289beceb8 583 } // NNCFIP
olympux 31:2e4b6de6c2f3 584
olympux 27:22f289beceb8 585 // if received NNCFIP, enter config mode
olympux 25:48dd18cc147c 586 if (config_mode_flag) {
olympux 31:2e4b6de6c2f3 587 while (n > 0) {
olympux 20:71c7950fdd91 588 // got some data, test it
olympux 27:22f289beceb8 589 DBG("UDP received (%s) from (%s:%d)", udp_receiving_buffer, ep_udp_client.get_address(), ep_udp_client.get_port());
olympux 26:09e0dd020900 590 process_config_command(udp_receiving_buffer, n);
olympux 20:71c7950fdd91 591 // wait to receive new config command
olympux 20:71c7950fdd91 592 udp_server.set_blocking(true);
olympux 20:71c7950fdd91 593 n = udp_server.receiveFrom(ep_udp_client, udp_receiving_buffer, sizeof(udp_receiving_buffer));
olympux 26:09e0dd020900 594 } // while (n > 0), config loop
olympux 25:48dd18cc147c 595 } // if (config_mode_flag)
olympux 29:bc052f283ada 596 // process control packages sent using UDP
olympux 29:bc052f283ada 597 else if ((n > 0) && (!discovery_mode_flag)) {
olympux 28:00c0c20d03c1 598 n = process_control_command(udp_receiving_buffer, n);
olympux 28:00c0c20d03c1 599 // send rpc reply back to client, NNIO protocol always returns 0
olympux 31:2e4b6de6c2f3 600 // RPC-style protocol
olympux 28:00c0c20d03c1 601 if (n > 0) {
olympux 31:2e4b6de6c2f3 602 network_output_buffer[n] = '\0';
olympux 31:2e4b6de6c2f3 603 udp_server.sendTo(ep_udp_client, network_output_buffer, strlen(network_output_buffer));
olympux 31:2e4b6de6c2f3 604 } // RPC-style protocol
olympux 31:2e4b6de6c2f3 605 else if (n == 0) {
olympux 31:2e4b6de6c2f3 606 // then, check query status command and sending protocol if required
olympux 31:2e4b6de6c2f3 607 if (udp_receiving_buffer[RECEIVING_PROTOCOL_COMMAND_POS] == QUERY_STATUS_COMMAND) {
olympux 31:2e4b6de6c2f3 608 DBG("Requested to send device status through UDP");
olympux 31:2e4b6de6c2f3 609 // sending protocol
olympux 31:2e4b6de6c2f3 610 update_sending_frame(network_output_buffer);
olympux 31:2e4b6de6c2f3 611 udp_server.sendTo(ep_udp_client, network_output_buffer, SENDING_PROTOCOL_LENGTH);
olympux 31:2e4b6de6c2f3 612 DBG("Sent");
olympux 31:2e4b6de6c2f3 613 }
olympux 32:db2e8ea06ee1 614 } // NNIO protocol
olympux 25:48dd18cc147c 615 }
olympux 3:972ed747474c 616 #endif
olympux 4:568c97f2a407 617 } // network processor
olympux 11:709f90a3b599 618 }
olympux 11:709f90a3b599 619
olympux 26:09e0dd020900 620
olympux 28:00c0c20d03c1 621 /*
olympux 28:00c0c20d03c1 622 * Process NNCF commands
olympux 28:00c0c20d03c1 623 */
olympux 26:09e0dd020900 624 void process_config_command(char* received_buffer, int len)
olympux 26:09e0dd020900 625 {
olympux 27:22f289beceb8 626 DBG("Processing configuration command");
olympux 31:2e4b6de6c2f3 627
olympux 26:09e0dd020900 628 // a configuration command always starts with NN
olympux 27:22f289beceb8 629 if ((received_buffer[0] == 'N') && (received_buffer[1] == 'N') &&
olympux 31:2e4b6de6c2f3 630 (received_buffer[2] == 'C') && (received_buffer[3] == 'F')) {
olympux 26:09e0dd020900 631 switch (len) {
olympux 31:2e4b6de6c2f3 632 // length = 6, a QUERY command (discovery command, TCP port, or UDP port)
olympux 31:2e4b6de6c2f3 633 // Format: NNCFDS, NNCFTP, NNCFUP, NNCFTM
olympux 30:15e23257e786 634 case QUERY_NETWORK_CONFIG_CMD_LENGTH: {
olympux 26:09e0dd020900 635 if (strstr(received_buffer, QUERY_IP_CMD) != NULL) {
olympux 26:09e0dd020900 636 udp_server.sendTo(ep_udp_client, eth.getIPAddress(), strlen(eth.getIPAddress()));
olympux 27:22f289beceb8 637 } // NNCFIP
olympux 26:09e0dd020900 638 else if (strstr(received_buffer, QUERY_SUBNET_CMD) != NULL) {
olympux 26:09e0dd020900 639 udp_server.sendTo(ep_udp_client, eth.getNetworkMask(), strlen(eth.getNetworkMask()));
olympux 27:22f289beceb8 640 } // NNCFSN
olympux 26:09e0dd020900 641 else if (strstr(received_buffer, QUERY_GATEWAY_CMD) != NULL) {
olympux 26:09e0dd020900 642 udp_server.sendTo(ep_udp_client, eth.getGateway(), strlen(eth.getGateway()));
olympux 27:22f289beceb8 643 } // NNCFGW
olympux 26:09e0dd020900 644 else if (strstr(received_buffer, QUERY_MAC_CMD) != NULL) {
olympux 26:09e0dd020900 645 udp_server.sendTo(ep_udp_client, eth.getMACAddress(), strlen(eth.getMACAddress()));
olympux 27:22f289beceb8 646 } // NNCFMC
olympux 26:09e0dd020900 647 // ask for TCP server port
olympux 26:09e0dd020900 648 else if (strstr(received_buffer, QUERY_TCP_PORT_CMD) != NULL) {
olympux 26:09e0dd020900 649 char port[5];
olympux 26:09e0dd020900 650 sprintf(port, "%5d", tcp_server_local_port);
olympux 26:09e0dd020900 651 udp_server.sendTo(ep_udp_client, port, strlen(port));
olympux 27:22f289beceb8 652 } // NNCFTP
olympux 26:09e0dd020900 653 // ask for UDP server port
olympux 26:09e0dd020900 654 else if (strstr(received_buffer, QUERY_UDP_PORT_CMD) != NULL) {
olympux 26:09e0dd020900 655 char port[5];
olympux 26:09e0dd020900 656 sprintf(port, "%5d", udp_server_local_port);
olympux 26:09e0dd020900 657 udp_server.sendTo(ep_udp_client, port, strlen(port));
olympux 27:22f289beceb8 658 } // NNCFUP
olympux 26:09e0dd020900 659 else if (strstr(received_buffer, QUERY_UPDATE_TIME_CMD) != NULL) {
olympux 26:09e0dd020900 660 #ifdef NTP
olympux 26:09e0dd020900 661 char str_time[50];
olympux 26:09e0dd020900 662
olympux 26:09e0dd020900 663 DBG("Trying to update time...");
olympux 26:09e0dd020900 664 if (ntp.setTime("0.pool.ntp.org") == 0) {
olympux 26:09e0dd020900 665 DBG("Set time successfully");
olympux 26:09e0dd020900 666 time_t ctTime;
olympux 26:09e0dd020900 667 ctTime = time(NULL);
olympux 26:09e0dd020900 668
olympux 26:09e0dd020900 669 DBG("Time is set to (UTC): %s", ctime(&ctTime));
olympux 26:09e0dd020900 670 sprintf(str_time, "%s", ctime(&ctTime));
olympux 26:09e0dd020900 671 udp_server.sendTo(ep_udp_client, str_time, strlen(str_time));
olympux 26:09e0dd020900 672 } else {
olympux 26:09e0dd020900 673 WARN("Error");
olympux 26:09e0dd020900 674 sprintf(str_time, "ERR");
olympux 26:09e0dd020900 675 udp_server.sendTo(ep_udp_client, str_time, strlen(str_time));
olympux 26:09e0dd020900 676 }
olympux 37:94b847fea94e 677 #else
olympux 26:09e0dd020900 678 WARN("NTP disabled");
olympux 26:09e0dd020900 679 sprintf(str_time, "DIS");
olympux 26:09e0dd020900 680 udp_server.sendTo(ep_udp_client, str_time, strlen(str_time));
olympux 26:09e0dd020900 681 #endif
olympux 27:22f289beceb8 682 } // NNCFTM
olympux 26:09e0dd020900 683 break;
olympux 30:15e23257e786 684 }
olympux 30:15e23257e786 685 // length = 19, SET NETWORK CONFIGURATION
olympux 30:15e23257e786 686 // Format: 4E 4E 43 46 C0 A8 00 78 FF FF FF 00 C0 A8 00 01 00 00 01
olympux 30:15e23257e786 687 // (NNCF; IP: 192.168.0.120; Subnet: 255.255.255.0; GW: 192.168.0.1; MAC: 0 0 1)
olympux 26:09e0dd020900 688 case SET_NETWORK_CONFIG_CMD_LENGTH: {
olympux 26:09e0dd020900 689 // check device id
olympux 27:22f289beceb8 690 char* id = strstr(received_buffer, DEVICE_CONFIG_CODE);
olympux 26:09e0dd020900 691 if (id == NULL)
olympux 26:09e0dd020900 692 break;
olympux 26:09e0dd020900 693 else if ((id - received_buffer) > 0)
olympux 26:09e0dd020900 694 break;
olympux 26:09e0dd020900 695
olympux 26:09e0dd020900 696 DBG("Received user configuration");
olympux 27:22f289beceb8 697 write_eeprom_network(&received_buffer[strlen(DEVICE_CONFIG_CODE)]); // parameters from 5th char, 15-bytes
olympux 33:c906ccc220ba 698 NVIC_SystemReset();
olympux 26:09e0dd020900 699 break;
olympux 26:09e0dd020900 700 }
olympux 26:09e0dd020900 701 // length = 12, SET TCP SERVER CONFIGURATION
olympux 26:09e0dd020900 702 // auto update & its time period, TCP server configuration (IP & port)
olympux 27:22f289beceb8 703 // Format: 4E 4E 43 46 'Y' 01 C0 A8 00 09 E0 2E (LSB MSB)
olympux 27:22f289beceb8 704 // NNCF Auto 1s 192.168.0.9 12000
olympux 26:09e0dd020900 705 case UPDATE_TCP_SERVER_INFO_COMMAND_LENGTH: {
olympux 27:22f289beceb8 706 char* id = strstr(received_buffer, DEVICE_CONFIG_CODE);
olympux 26:09e0dd020900 707 if (id == NULL)
olympux 26:09e0dd020900 708 break;
olympux 26:09e0dd020900 709 else if ((id - received_buffer) > 0)
olympux 26:09e0dd020900 710 break;
olympux 26:09e0dd020900 711
olympux 26:09e0dd020900 712 DBG("Received TCP server configuration");
olympux 27:22f289beceb8 713 write_eeprom_tcpserver(&received_buffer[strlen(DEVICE_CONFIG_CODE)]); // parameters from 5th char
olympux 33:c906ccc220ba 714 NVIC_SystemReset();
olympux 26:09e0dd020900 715 break;
olympux 26:09e0dd020900 716 }
olympux 26:09e0dd020900 717 default:
olympux 26:09e0dd020900 718 break;
olympux 26:09e0dd020900 719 } // switch (n), check configuration command length
olympux 27:22f289beceb8 720 } // if starts with NNCF, a config command
olympux 30:15e23257e786 721 else { // if not a configuration command
olympux 26:09e0dd020900 722 }
olympux 26:09e0dd020900 723 }
olympux 26:09e0dd020900 724
olympux 12:7c152c0ca4d8 725 /*
olympux 30:15e23257e786 726 * Procedure to process receiving protocol, which includes command to control outputs.
olympux 30:15e23257e786 727 * Support both NNIO and RPC-style commands.
olympux 30:15e23257e786 728 * RPC always starts with '/'.
olympux 30:15e23257e786 729 * Return:
olympux 30:15e23257e786 730 * 0 if NNIO protocol;
olympux 30:15e23257e786 731 * length of rpc output buffer if rpc;
olympux 30:15e23257e786 732 * -1 if rpc failed
olympux 28:00c0c20d03c1 733 */
olympux 28:00c0c20d03c1 734 int process_control_command(char* received_buffer, int len)
olympux 26:09e0dd020900 735 {
olympux 26:09e0dd020900 736 char* received_frame;
olympux 30:15e23257e786 737 bool rpc_style;
olympux 26:09e0dd020900 738 int pos;
olympux 31:2e4b6de6c2f3 739 char inbuf[NET_BUF_LEN];
olympux 31:2e4b6de6c2f3 740
olympux 27:22f289beceb8 741 DBG("Processing control command");
olympux 31:2e4b6de6c2f3 742
olympux 30:15e23257e786 743 /*
olympux 30:15e23257e786 744 * This section is for RPC-style command
olympux 30:15e23257e786 745 */
olympux 30:15e23257e786 746 // check if it is a RPC-style command
olympux 30:15e23257e786 747 rpc_style = false;
olympux 27:22f289beceb8 748 strncpy(inbuf, received_buffer, len);
olympux 27:22f289beceb8 749 inbuf[len] = '\r'; // use inbuf for RPC protocol
olympux 27:22f289beceb8 750 inbuf[len+1] = '\n';
olympux 27:22f289beceb8 751 inbuf[len+2] = '\0'; // add CR-LF
olympux 27:22f289beceb8 752 if ((len > 0) && (inbuf[0] == '/')) {
olympux 34:32299b819067 753 char obj_name[16];
olympux 34:32299b819067 754 bool ok;
olympux 31:2e4b6de6c2f3 755
olympux 30:15e23257e786 756 rpc_style = true;
olympux 29:bc052f283ada 757 // find RPC object name
olympux 29:bc052f283ada 758 for (int i = 1; i < strlen(inbuf); i++) {
olympux 29:bc052f283ada 759 if (inbuf[i] != '/') {
olympux 29:bc052f283ada 760 obj_name[i-1] = inbuf[i];
olympux 31:2e4b6de6c2f3 761 } else {
olympux 29:bc052f283ada 762 obj_name[i-1] = '\0';
olympux 29:bc052f283ada 763 break;
olympux 29:bc052f283ada 764 }
olympux 29:bc052f283ada 765 }
olympux 28:00c0c20d03c1 766 DBG("Rpc command = %s", inbuf);
olympux 29:bc052f283ada 767 /*
olympux 29:bc052f283ada 768 * execute RPC command, return reply length and reply in rpc_outbuf
olympux 29:bc052f283ada 769 */
olympux 34:32299b819067 770 ok = RPC::call(inbuf, network_output_buffer);
olympux 34:32299b819067 771 if (ok) {
olympux 29:bc052f283ada 772 // re-arrange output buffer as following: object_name:output_value
olympux 31:2e4b6de6c2f3 773 strcpy(inbuf, network_output_buffer); // use inbuf as temp
olympux 31:2e4b6de6c2f3 774 strcpy(network_output_buffer, obj_name); // rpc object name
olympux 31:2e4b6de6c2f3 775 strcat(network_output_buffer, ":");
olympux 31:2e4b6de6c2f3 776 strcat(network_output_buffer, inbuf); // concat rpc reply
olympux 31:2e4b6de6c2f3 777 strcat(network_output_buffer, "\r\n"); // CR-LF
olympux 31:2e4b6de6c2f3 778 int j = strlen(network_output_buffer);
olympux 31:2e4b6de6c2f3 779 DBG("Reply of rpc command on \"%s\" (%d bytes): %s", obj_name, j, network_output_buffer);
olympux 29:bc052f283ada 780 return j; // return length of rpc_outbuf
olympux 31:2e4b6de6c2f3 781 } else {
olympux 27:22f289beceb8 782 ERR("Failed: %s", inbuf);
olympux 28:00c0c20d03c1 783 return -1;
olympux 27:22f289beceb8 784 }
olympux 27:22f289beceb8 785 }
olympux 31:2e4b6de6c2f3 786
olympux 28:00c0c20d03c1 787 /*
olympux 28:00c0c20d03c1 788 * This section below is for NNIO protocol
olympux 28:00c0c20d03c1 789 */
olympux 30:15e23257e786 790 while ((!rpc_style) && (len >= RECEIVING_PROTOCOL_LENGTH)) {
olympux 26:09e0dd020900 791 // find device ID
olympux 26:09e0dd020900 792 DBG("Checking device ID...");
olympux 27:22f289beceb8 793 char* id = strstr(received_buffer, DEVICE_CONTROL_CODE);
olympux 26:09e0dd020900 794 if (id == NULL) {
olympux 26:09e0dd020900 795 DBG("No device ID found");
olympux 26:09e0dd020900 796 break;
olympux 26:09e0dd020900 797 }
olympux 26:09e0dd020900 798 pos = id - received_buffer;
olympux 26:09e0dd020900 799 DBG("Found a frame at %d", pos);
olympux 31:2e4b6de6c2f3 800
olympux 26:09e0dd020900 801 // extract this frame
olympux 26:09e0dd020900 802 received_frame = &received_buffer[pos];
olympux 26:09e0dd020900 803 // calculate the rest
olympux 26:09e0dd020900 804 received_buffer = &received_buffer[pos + RECEIVING_PROTOCOL_LENGTH];
olympux 26:09e0dd020900 805 len -= RECEIVING_PROTOCOL_LENGTH;
olympux 31:2e4b6de6c2f3 806
olympux 26:09e0dd020900 807 // process this received frame
olympux 26:09e0dd020900 808 // firstly, update outputs if required
olympux 26:09e0dd020900 809 // digital outputs
olympux 26:09e0dd020900 810 if (received_frame[RECEIVING_PROTOCOL_EN_DO_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) {
olympux 26:09e0dd020900 811 DBG("Update digital outputs");
olympux 26:09e0dd020900 812 char str_dout[9];
olympux 26:09e0dd020900 813 memcpy(str_dout, &received_frame[RECEIVING_PROTOCOL_DO_POS], 8);
olympux 26:09e0dd020900 814 str_dout[8] = '\0';
olympux 26:09e0dd020900 815 update_digital_outputs(str_dout);
olympux 26:09e0dd020900 816 }
olympux 26:09e0dd020900 817 // analog output 0
olympux 26:09e0dd020900 818 if (received_frame[RECEIVING_PROTOCOL_EN_A0O_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) {
olympux 26:09e0dd020900 819 DBG("Update analog output 0");
olympux 26:09e0dd020900 820 //TODO Update analog output
olympux 26:09e0dd020900 821 }
olympux 26:09e0dd020900 822 // analog output 1
olympux 26:09e0dd020900 823 if (received_buffer[RECEIVING_PROTOCOL_EN_A1O_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) {
olympux 26:09e0dd020900 824 DBG("Update analog output 1");
olympux 26:09e0dd020900 825 //TODO Update analog output
olympux 26:09e0dd020900 826 }
olympux 26:09e0dd020900 827 // UART
olympux 26:09e0dd020900 828 if (received_frame[RECEIVING_PROTOCOL_EN_UART_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) {
olympux 26:09e0dd020900 829 DBG("UART data: ");
olympux 26:09e0dd020900 830 char str_uart[33];
olympux 26:09e0dd020900 831 memcpy(str_uart, &received_frame[RECEIVING_PROTOCOL_UART_POS], 32);
olympux 26:09e0dd020900 832 str_uart[32] = '\0';
olympux 26:09e0dd020900 833 uart.printf("%s\r\n", str_uart);
olympux 26:09e0dd020900 834 }
olympux 26:09e0dd020900 835 }
olympux 31:2e4b6de6c2f3 836
olympux 27:22f289beceb8 837 DBG("Successfully processed.");
olympux 28:00c0c20d03c1 838 return 0;
olympux 26:09e0dd020900 839 }
olympux 26:09e0dd020900 840
olympux 26:09e0dd020900 841
olympux 26:09e0dd020900 842 /*
olympux 26:09e0dd020900 843 * W5500 Ethernet init
olympux 26:09e0dd020900 844 */
olympux 31:2e4b6de6c2f3 845 int ethernet_init(void)
olympux 31:2e4b6de6c2f3 846 {
olympux 26:09e0dd020900 847 int dhcp_ret, ret;
olympux 31:2e4b6de6c2f3 848
olympux 27:22f289beceb8 849 DBG("Initialising ethernet...");
olympux 31:2e4b6de6c2f3 850
olympux 26:09e0dd020900 851 // if not configured, try dhcp
olympux 26:09e0dd020900 852 dhcp_ret = -1;
olympux 26:09e0dd020900 853 if (configured_ip != DEFAULT_ENABLE_FLAG_VALUE) {
olympux 27:22f289beceb8 854 DBG("Connecting to DHCP server...");
olympux 26:09e0dd020900 855 dhcp_ret = eth.init(u8mac);
olympux 26:09e0dd020900 856 if (dhcp_ret == 0)
olympux 26:09e0dd020900 857 dhcp_ret = eth.connect();
olympux 26:09e0dd020900 858 }
olympux 31:2e4b6de6c2f3 859
olympux 26:09e0dd020900 860 if (dhcp_ret != 0) {
olympux 26:09e0dd020900 861 DBG("No DHCP, load static IP configuration");
olympux 26:09e0dd020900 862 ret = eth.init(u8mac, str_ip_addr, str_ip_subnet, str_ip_gateway); // static
olympux 26:09e0dd020900 863 } else {
olympux 26:09e0dd020900 864 snprintf(str_ip_addr, 16, "%s", eth.getIPAddress());
olympux 26:09e0dd020900 865 snprintf(str_ip_subnet, 16, "%s", eth.getNetworkMask());
olympux 26:09e0dd020900 866 snprintf(str_ip_gateway, 16, "%s", eth.getGateway());
olympux 26:09e0dd020900 867 ret = 0;
olympux 26:09e0dd020900 868 }
olympux 26:09e0dd020900 869
olympux 26:09e0dd020900 870 if (ret == 0) {
olympux 26:09e0dd020900 871 DBG("Initialized, MAC: %s", eth.getMACAddress());
olympux 26:09e0dd020900 872 } else {
olympux 26:09e0dd020900 873 ERR("Error eth.init() - ret = %d", ret);
olympux 26:09e0dd020900 874 return -1;
olympux 26:09e0dd020900 875 }
olympux 26:09e0dd020900 876
olympux 26:09e0dd020900 877 ret = eth.connect();
olympux 26:09e0dd020900 878 if (!ret) {
olympux 26:09e0dd020900 879 DBG("IP: %s, MASK: %s, GW: %s", eth.getIPAddress(), eth.getNetworkMask(), eth.getGateway());
olympux 26:09e0dd020900 880 } else {
olympux 26:09e0dd020900 881 ERR("Error eth.connect() - ret = %d", ret);
olympux 26:09e0dd020900 882 return -1;
olympux 26:09e0dd020900 883 }
olympux 31:2e4b6de6c2f3 884
olympux 26:09e0dd020900 885 return 0;
olympux 26:09e0dd020900 886 }
olympux 26:09e0dd020900 887
olympux 26:09e0dd020900 888
olympux 26:09e0dd020900 889 /*
olympux 26:09e0dd020900 890 * Update digital outputs according to receiving protocol
olympux 12:7c152c0ca4d8 891 */
olympux 31:2e4b6de6c2f3 892 void update_digital_outputs(char* buf)
olympux 31:2e4b6de6c2f3 893 {
olympux 18:ca499a2e7da6 894 DBG("Digital outputs: %s", buf);
olympux 31:2e4b6de6c2f3 895
olympux 12:7c152c0ca4d8 896 dout0 = (buf[0] == DIGITAL_HIGH)? 1 : 0;
olympux 12:7c152c0ca4d8 897 dout1 = (buf[1] == DIGITAL_HIGH)? 1 : 0;
olympux 12:7c152c0ca4d8 898 dout2 = (buf[2] == DIGITAL_HIGH)? 1 : 0;
olympux 12:7c152c0ca4d8 899 dout3 = (buf[3] == DIGITAL_HIGH)? 1 : 0;
olympux 12:7c152c0ca4d8 900 dout4 = (buf[4] == DIGITAL_HIGH)? 1 : 0;
olympux 12:7c152c0ca4d8 901 dout5 = (buf[5] == DIGITAL_HIGH)? 1 : 0;
olympux 12:7c152c0ca4d8 902 dout6 = (buf[6] == DIGITAL_HIGH)? 1 : 0;
olympux 12:7c152c0ca4d8 903 dout7 = (buf[7] == DIGITAL_HIGH)? 1 : 0;
olympux 12:7c152c0ca4d8 904 }
olympux 12:7c152c0ca4d8 905
olympux 26:09e0dd020900 906 /*
olympux 26:09e0dd020900 907 * Prepare a frame for sending protocol, which includes status of I/Os
olympux 26:09e0dd020900 908 */
olympux 31:2e4b6de6c2f3 909 void update_sending_frame(char* buf)
olympux 31:2e4b6de6c2f3 910 {
olympux 27:22f289beceb8 911 memcpy(&buf[SENDING_PROTOCOL_ID_POS], DEVICE_CONTROL_CODE, 4); // device id
olympux 12:7c152c0ca4d8 912 memcpy(&buf[SENDING_PROTOCOL_MAC_POS], &u8mac, 6);
olympux 12:7c152c0ca4d8 913 memcpy(&buf[SENDING_PROTOCOL_IP_POS], &u8ip_addr, 4);
olympux 31:2e4b6de6c2f3 914
olympux 12:7c152c0ca4d8 915 buf[SENDING_PROTOCOL_DI_POS+0] = (din0 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 916 buf[SENDING_PROTOCOL_DI_POS+1] = (din1 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 917 buf[SENDING_PROTOCOL_DI_POS+2] = (din2 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 918 buf[SENDING_PROTOCOL_DI_POS+3] = (din3 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 919 buf[SENDING_PROTOCOL_DI_POS+4] = (din4 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 920 buf[SENDING_PROTOCOL_DI_POS+5] = (din5 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 921 buf[SENDING_PROTOCOL_DI_POS+6] = (din6 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 922 buf[SENDING_PROTOCOL_DI_POS+7] = (din7 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 31:2e4b6de6c2f3 923
olympux 12:7c152c0ca4d8 924 buf[SENDING_PROTOCOL_DO_POS+0] = (dout0 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 925 buf[SENDING_PROTOCOL_DO_POS+1] = (dout1 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 926 buf[SENDING_PROTOCOL_DO_POS+2] = (dout2 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 927 buf[SENDING_PROTOCOL_DO_POS+3] = (dout3 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 928 buf[SENDING_PROTOCOL_DO_POS+4] = (dout4 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 929 buf[SENDING_PROTOCOL_DO_POS+5] = (dout5 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 930 buf[SENDING_PROTOCOL_DO_POS+6] = (dout6 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 12:7c152c0ca4d8 931 buf[SENDING_PROTOCOL_DO_POS+7] = (dout7 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
olympux 31:2e4b6de6c2f3 932
olympux 15:edeb0aed160d 933 uint16_t val = ain0.read_u16(); // 16-bits normalised
olympux 15:edeb0aed160d 934 memcpy(&buf[SENDING_PROTOCOL_AI0_POS], &val, 2); // LSB MSB
olympux 15:edeb0aed160d 935 val = ain1.read_u16(); // 16-bits normalised
olympux 15:edeb0aed160d 936 memcpy(&buf[SENDING_PROTOCOL_AI1_POS], &val, 2); // LSB MSB
olympux 23:47ee805435b1 937 val = 0x1234;
olympux 15:edeb0aed160d 938 memcpy(&buf[SENDING_PROTOCOL_AO0_POS], &val, 2); // LSB MSB
olympux 23:47ee805435b1 939 val = 0x5678;
olympux 15:edeb0aed160d 940 memcpy(&buf[SENDING_PROTOCOL_AO1_POS], &val, 2); // LSB MSB
olympux 12:7c152c0ca4d8 941 buf[SENDING_PROTOCOL_CR_POS] = 0x0D;
olympux 12:7c152c0ca4d8 942 buf[SENDING_PROTOCOL_CR_POS+1] = '\0';
olympux 4:568c97f2a407 943 }