ClearCore Library
Loading...
Searching...
No Matches
EthernetTcpServerHelloWorld_manual.cpp

Return to SDK Examples for Microchip Studio

1/*
2 * Title: EthernetTCPServer_manualClientManagement
3 *
4 * Objective:
5 * This example demonstrates how to configure a ClearCore as a TCP server to
6 * send and receive TCP datagrams (packets).
7 *
8 * Description:
9 * This example configures a ClearCore device to act as a TCP server.
10 * This server can receive connections from several other devices acting as TCP
11 * clients to exchange data over ethernet TCP.
12 * This simple example accepts connection requests from clients, checks for
13 * incoming data from connected devices, and sends a simple "Hello
14 * client" response.
15 * A partner project, EthernetTcpClientHelloWorld, can be used to configure
16 * another ClearCore as a client device.
17 *
18 * Setup:
19 * 1. Set the usingDhcp boolean as appropriate. If not using DHCP, specify static
20 * IP and network information.
21 * 2. Ensure the server and client are setup to communicate on the same network.
22 * If server and client devices are directly connected (as opposed to through a switch)
23 * an ethernet crossover cable may be required.
24 * 3. It may be helpful to use another application to view serial output from
25 * each device. PuTTY is one such application: https://www.putty.org/
26 *
27 * Links:
28 * ** ClearCore Documentation: https://teknic-inc.github.io/ClearCore-library/
29 * ** ClearCore Manual: https://www.teknic.com/files/downloads/clearcore_user_manual.pdf
30 *
31 * Copyright (c) 2022 Teknic Inc. This work is free to use, copy and distribute under the terms of
32 * the standard MIT permissive software license which can be found at https://opensource.org/licenses/MIT
33 */
34
35#include "ClearCore.h"
36#include "EthernetTcpServer.h"
37
38// The port number on the server over which packets will be sent/received
39#define PORT_NUM 8888
40
41// The maximum number of characters to receive from an incoming packet
42#define MAX_PACKET_LENGTH 100
43// Buffer for holding received packets
44unsigned char packetReceived[MAX_PACKET_LENGTH];
45// Buffer for holding packets to send
46char packetToSend[MAX_PACKET_LENGTH];
47
48// Set total number of clients the server will accept
49#define NUMBER_OF_CLIENTS 6
50
51// Set usingDhcp to false to use user defined network settings
52bool usingDhcp = true;
53
54// Array of output LEDs to indicate client connections
55// NOTE: only connectors IO0 through IO5 can be configured as digital outputs (LEDs)
56Connector *const outputLEDs[6] = {
57 &ConnectorIO0, &ConnectorIO1, &ConnectorIO2, &ConnectorIO3, &ConnectorIO4, &ConnectorIO5
58};
59
60
61int main(void) {
62 // Set up serial communication between ClearCore and PC serial terminal
63 ConnectorUsb.Mode(Connector::USB_CDC);
64 ConnectorUsb.Speed(9600);
65 ConnectorUsb.PortOpen();
66 uint32_t timeout = 5000;
67 uint32_t startTime = Milliseconds();
68 while (!ConnectorUsb && Milliseconds() - startTime < timeout) {
69 continue;
70 }
71
72 // Set connectors IO0-IO5 as a digital outputs
73 // When an outputLED's state is true, a LED will light on the
74 // ClearCore indicating a successful connection to a client
75 for(int i=0; i<6; i++){
76 outputLEDs[i]->Mode(Connector::OUTPUT_DIGITAL);
77 }
78
79 // Make sure the physical link is active before continuing
80 while (!EthernetMgr.PhyLinkActive()) {
81 ConnectorUsb.SendLine("The Ethernet cable is unplugged...");
82 Delay_ms(1000);
83 }
84
85 //To configure with an IP address assigned via DHCP
87 if (usingDhcp) {
88 // Use DHCP to configure the local IP address
89 bool dhcpSuccess = EthernetMgr.DhcpBegin();
90 if (dhcpSuccess) {
91 ConnectorUsb.Send("DHCP successfully assigned an IP address: ");
93 }
94 else {
95 ConnectorUsb.SendLine("DHCP configuration was unsuccessful!");
96 while (true) {
97 // TCP will not work without a configured IP address
98 continue;
99 }
100 }
101 } else {
102 // Configure with a manually assigned IP address
103
104 // Set ClearCore's IP address
105 IpAddress ip = IpAddress(192, 168, 0, 100);
107 ConnectorUsb.Send("Assigned manual IP address: ");
109
110 // Optionally, set additional network addresses if needed
111
112 //IpAddress gateway = IpAddress(192, 168, 1, 1);
113 //IpAddress netmask = IpAddress(255, 255, 255, 0);
114 //EthernetMgr.GatewayIp(gateway);
115 //EthernetMgr.NetmaskIp(netmask);
116 }
117
118
119 // Initialize the ClearCore as a server
120 // Clients connect on specified port (8888 by default)
121 EthernetTcpServer server = EthernetTcpServer(PORT_NUM);
122
123 // Initialize an array of clients
124 // This array holds the information of any client that
125 // is currently connected to the server, and is used by the
126 // server to interact with these clients
127 EthernetTcpClient clients[NUMBER_OF_CLIENTS];
128 // Initialize an temporary client for client management
129 EthernetTcpClient tempClient;
130
131 bool newClient = 0;
132
133 // Start listening for TCP connections
134 server.Begin();
135
136 ConnectorUsb.SendLine("Server now listening for client connections...");
137
138 // Resets a timer used to display a list of connected clients
139 startTime = 0;
140
141 // Connect to clients, and send/receive packets
142 while(true){
143
144 // Obtain a reference to a connected client
145 // This function returns a specific client once per connection attempt
146 // To maintain a connection with a client using Accept()
147 // some basic client management must be performed
148 tempClient = server.Accept();
149
150 // Checks if server.Accept() has returned a new client
151 if(tempClient.Connected()){
152 newClient = 1;
153
154 for(int i=0; i<NUMBER_OF_CLIENTS; i++){
155 //Checks for an available location to store a new client
156 if(!clients[i].Connected()){
157 clients[i].Close();
158 clients[i] = tempClient;
159 ConnectorUsb.Send(clients[i].RemoteIp().StringValue());
160 ConnectorUsb.SendLine(" has been connected");
161 newClient = 0;
162 break;
163 }
164 }
165 // Rejects client if the client list is full
166 if(newClient == 1){
167 newClient = 0;
168 tempClient.Send("This server has reached its max number of clients. Closing connection.");
169 sprintf(packetToSend, "This server has reached its max number of clients. Closing connection to (%s).", tempClient.RemoteIp().StringValue());
170 ConnectorUsb.SendLine(packetToSend);
171 tempClient.Close();
172 }
173 }
174
175 // Loops through list of clients to receive/send messages
176 for(int i=0; i<NUMBER_OF_CLIENTS; i++){
177 if (clients[i].Connected()) {
178
179 // Indicate connection on corresponding output LED
180 outputLEDs[i]->State(true);
181
182 // Check if client has incoming data available
183 if(clients[i].BytesAvailable()){
184 sprintf(packetToSend, "Read the following from the client(%s): ", clients[i].RemoteIp().StringValue());
185 ConnectorUsb.Send(packetToSend);
186 // Read packet from the client
187 while (clients[i].BytesAvailable()) {
188 // Send the data received from the client over a serial port
189 clients[i].Read(packetReceived, MAX_PACKET_LENGTH);
190 ConnectorUsb.Send((char *)packetReceived);
191
192 // Clear the message buffer for the next iteration of the loop
193 for(int i=0; i<MAX_PACKET_LENGTH; i++){
194 packetReceived[i]=NULL;
195 }
196 }
198
199 //Sends unique response to the client
200 sprintf(packetToSend, "Hello client %s",clients[i].RemoteIp().StringValue());
201 if(clients[i].Send(packetToSend) == 0){
202 // If the message was unable to send, close the client connection
203 clients[i].Close();
204 sprintf(packetToSend, "Client (%s) has been removed from client list. ", clients[i].RemoteIp().StringValue());
205 ConnectorUsb.Send(packetToSend);
206 clients[i] = EthernetTcpClient();
207
208 // Indicate loss of connection by turning off corresponding LED
209 outputLEDs[i]->State(false);
210 }
211
212 }
213
214 } else{
215 // Removes any disconnected clients
216 if(clients[i].RemoteIp() != IpAddress(0,0,0,0)){
217 sprintf(packetToSend, "Client (%s) has been removed from client list. ", clients[i].RemoteIp().StringValue());
218 ConnectorUsb.Send(packetToSend);
219 clients[i].Close();
220 clients[i] = EthernetTcpClient();
221
222 // Indicate loss of connection by turning off corresponding LED
223 outputLEDs[i]->State(false);
224 }
225 }
226 }
227
228 // Make sure the physical link is active before continuing
229 while (!EthernetMgr.PhyLinkActive()) {
230 ConnectorUsb.SendLine("The Ethernet cable is unplugged...");
231 Delay_ms(1000);
232 }
233
234 // Print out a list of current clients
235 int delay = 5000;
236 if(Milliseconds()- startTime > delay){
237 ConnectorUsb.SendLine("List of current clients: ");
238 for(int i=0; i<NUMBER_OF_CLIENTS; i++){
239 if(clients[i].RemoteIp() != IpAddress(0,0,0,0)){
240 sprintf(packetToSend, "Client %i = %s", i, clients[i].RemoteIp().StringValue());
241 ConnectorUsb.SendLine(packetToSend);
242 }
243 }
244 startTime = Milliseconds();
245 }
246
247 // Perform any necessary periodic ethernet updates
248 // Must be called regularly when actively using ethernet
250 }
251}
252
void Delay_ms(uint32_t ms)
Blocks operations for ms milliseconds.
Definition SysTiming.h:287
uint32_t Milliseconds(void)
Number of milliseconds since the ClearCore was initialized.
volatile const bool & PhyLinkActive()
Check the link status from the PHY.
Definition EthernetManager.h:136
IpAddress LocalIp()
Get the local IP address.
void Refresh()
Perform any necessary periodic Ethernet and LwIP updates.
bool DhcpBegin()
Set up DHCP connection to retrieve local IP.
void Setup()
Setup LwIP with the local network interface.
bool SendLine()
Send carriage return and newline characters.
Definition ISerial.h:162
virtual bool Speed(uint32_t bitsPerSecond)=0
Change the baud rate for the port.
bool Send(const char *buffer, size_t bufferSize)
Send the array of characters out the port.
Definition ISerial.h:173
char * StringValue()
Returns a string representation of the IP Address.
Definition IpAddress.h:96
void PortOpen() override
virtual ConnectorModes Mode() override
Get the connector's operational mode.
Definition SerialUsb.h:210
SerialUsb ConnectorUsb
USB connector instance.
EthernetManager & EthernetMgr
Ethernet manager.