Mega mit Ethernet Shield als Client und Server

Hallo,

ich betreibe meinen Mega2560 zur Zeit als Datenlogger. Die Daten kommen über den Telnet-Client rein und werden auf der SD-Karte abgespeichert.
Um die gespeicherten Dateien auf meinen PC zu bekommen muss ich immer die SD-Karte aus dem Slot nehmen, am PC kopieren und dann wieder einstecken. Hilfreich hat sich dann ein Restart erwiesen.
Jetzt hab ich gestern einen Beitrag gefunden, mit dem man Dateien übers Ethernet auslesen kann.SDWebBrowse/SDWebBrowse.ino at master · adafruit/SDWebBrowse · GitHub
Den Code kurz angepasst und auf den Mega geschossen funktioniert prima. Allerdings nutzt er eine andere SD-Lib. (SdFat)
Jetzt wärs natürlich schön, wenn beides gemeinsam auf dem Arduino laufen würde.

Aber für meine Anwendung muss der Arduino als Telnet-Client laufen und für das Datenkopieren als Webserver.

Gibts da irgendeine Chance, daß man da beides in einer Software zum Laufen bringt? Die Deklaration "EthernetClient client;" bzw. "EthernetServer server(80);" geschieht ja am Anfang ausserhalb des Codes. Kann mir jetzt nicht vorstellen, wie man da per Software umschalten kann.

gruß/hk007

Es geht beides. Es wird halt auf 2 Ports gelauscht, sowas hab ich auch schon gebaut. Bei mir reichte es, das der Zugriff exkuliv war. Also während einer telnet-Verbindung war http nicht möglich und umgekehrt.
Falls Dir das reicht, kann ich die Lösung mal rauskramen.
Mario.

Hi mkl0815,
ja, das würde mir reichen.
ich könnte dann immer auf Webserver bleiben und alle 10 Minuten den Telnet kurz starten.

Es wird halt auf 2 Ports gelauscht

Die Aussage macht mich aber etwas stutzig. Hört sich eher nach 2mal Server an.

Sorry, mein Fehler. Der Arduino ist ja telnet-Client. Das sollte aber trotzdem gehen.

[BettelModus an]
Falls Dir das reicht, kann ich die Lösung mal rauskramen.
[BettelModus aus] :cold_sweat:

Hier mal der aufs wesentliche abgespeckte Code:

/*
 * Arduino Server
 * (c) 2012 - Mario Keller
 * 
 */


#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h> 


//default config is used if no user-config is stored in the eeprom
//or factory reset pin (3) is set to GND
byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEE };
byte ip[] = {
  192,168,0,200};
byte gateway[] = {
  192, 168, 0, 1 };
byte subnet[]  = {
  255, 255, 255, 0 };
byte bc[] = { 
  192, 168,0, 255 };

// Other global variables
#define textBuffSize 120 //length of longest command string plus two spaces for CR + LF

//text buffer for incoming commands
char textBuff[textBuffSize]; 

//counter of recieved characters
int charsReceived = 0;

//store if we have an active client connection
boolean connectFlag = false; 
boolean isHTTP = false;

//implement some kind of timeout of telnet connections
unsigned long timeOfLastActivity; //time in milliseconds of last activity
unsigned long allowedConnectTime = 60000; //one minute
unsigned long allowedHTTPTime = 10000; //ten seconds

//listen on port 23 (telnet)
EthernetServer server(23); 

//listen on port 23 (telnet)
EthernetServer http(80); 

//client that holds an incoming connection
EthernetClient client = 0; 


void setup()
{
  //start listening service
  Ethernet.begin(mac, ip, gateway, subnet);
  
  //start telnet-server
  server.begin();
  
  //start http-server
  http.begin();
  
}

/****************************************************************************** 
 *
 * MAIN LOOP
 *
 * just look for an active connection and delegate incoming data
 *
 ******************************************************************************/
void loop()
{
  // look to see if a new telnet connection is created,
  // print welcome message, set connected flag
  if (server.available() && !connectFlag) {
    connectFlag = 1;
    isHTTP = false;
    client = server.available();
    client.println("\nArduino Server");
    client.println("? for help");
    printPrompt();
  }

  // look to see if a new http-connection is created,
  // connection is only accepted if no active connection exists
  // set connected flag
  if (http.available() && !connectFlag) {
    connectFlag = 1;
    isHTTP = true;
    client = http.available();
  }
  
  // check to see if text received on Ethernet interface
  if (!isHTTP && client.connected() && client.available()) getReceivedText();

  // check to see if text received on Ethernet interface
  if (isHTTP && client.connected() && client.available()) getHTTPRequest();
  
  // check to see if connection has timed out
  if(connectFlag) checkConnectionTimeout();

}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//
// HELPER FUNCTIONS
//
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////


/**************************************************
 * print a prompt on the client side
 **************************************************/
void printPrompt()
{
  timeOfLastActivity = millis();
  client.flush();
  charsReceived = 0; //count of characters received
  client.print("\n>");
}

/************************************************************
 * check if we ran into a timeout for the current connection
 ************************************************************/
void checkConnectionTimeout()
{
  //close timed out telnet connection
  if(!isHTTP && millis() - timeOfLastActivity > allowedConnectTime) {
    client.println();
    client.println("Timeout disconnect.");
    client.stop();
    connectFlag = 0;
  }
  //close timed out http connection
  if(isHTTP && millis() - timeOfLastActivity > allowedHTTPTime) {
    client.stop();
    connectFlag = 0;
  }
}

void getHTTPRequest() {
  //handle http-request
  if (client.available()) {
    char c = client.read();
  }  
}

/**************************************************
 * read characters out of the current connection
 * and fill up the input buffer
 **************************************************/
void getReceivedText()
{
  //just handle incoming telnet traffic here
}

Wie gesagt, hier sind es zwei Server die lauschen, im Prinzip ist es aber nix anderes, wenn Du einen Client hast, der bereits mit einer Gegenstelle kommuniziert und einen Server der lauscht. Der Trick ist, dafür zu sorgen, das sich beide nicht in die Quere kommen.

Wie funktioniert denn bei Dir die Telnetverbindung? Wird die permanent offen gehalten, oder baust Du die bei jedem Mal Datenabfragen neu auf?

Hi Mario,
werd mir den Code mal heute Abend reinziehen und versuchen zu verstehen.

Wie funktioniert denn bei Dir die Telnetverbindung? Wird die permanent offen gehalten, oder baust Du die bei jedem Mal Datenabfragen neu auf?

Ich mach die Verbindung auf, lese die Daten und beende die Verbindung mit client.stop()

Seh ich die Abfolge so richtig:

#include <SD.h>          
#include <SPI.h>
#include <Ethernet.h>

// Definition MAC und IP-Adresse des Arduino:
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,90);
IPAddress t_server (192,168,1,95); 
EthernetClient client;
EthernetServer server(80);

void setup() {
  Ethernet.begin(mac, ip);
  server.begin();
}
void loop() {
  // die Unterfunktionen sinnvoll und v.a. nicht gleichzeitig aufrufen.
  Ethserver();
  Ethclient();
  sdCard();
}
void Ethserver() {
  // code
}
void Ethclient() {
  client.connect(t_server, 23);
  // code
  client.stop();
}
void sdCard() {
  // code
}

Ist die Abfolge und das Einbauen der Befehle in die Setup-Routine und in das zyklische Programm so richtig?
Bei einem Punkt bin ich mir nicht so sicher:
Ich schalte immer mit Pin 4 und Pin 10 zwischen SD-Karte und WIZ-Chip um. (Hab das Ethernet-Shield)
Momentan fahr ich ja nur den Telnet-Client. Den stoppe ich am Ende des Datenaustausches immer, und schreibe dann auf die SD-Karte.
Wie ist das bei einem aktiven Serverdienst? Was passiert da, wenn ich dem WIZ-Chip mittendrin das CS-Signal nehme?
Vorausgesetzt natürlich, daß keine Verbindung aktiv ist.

gruß/hk007