Webserver en pingen

Ik heb weer een vraagje :grinning:

Aangezien het andere projectje op onderdelen ben ik weer wat aan het testen geslagen. Het doel is om een miniwebserver te laten draaien met simpel 2 knoppen (lamp aan en lamp uit). De webserver moet dus meerdere URLs aankunnen. Daarnaast moet dezelfde Arduino iedere 10 minuten een PING sturen naar 2 verschillende IPs om te bepalen of deze in het netwerk aanwezig zijn.

De hardware die ik heb: -Arduino Nano 3.0 -Ethernetboard met 28j60

Het Ethernetboard krijg ik aan de gang met Ethercard en UIPEthernet.

UIPEthernet: -Webpagina tonen werkt (Example code) -Ik heb geen idee hoe je moet pingen. Ik heb een library gevonden maar die werkt niet met UIPEthernet. Moet googlen kom ik er niet verder mee

Ethercard: -Webpagina tonen werkt (Example code) -Pingen naar 1 host werkt maar als ik na die ping een ander IP parse dan komt er als IP 0.0.0.0

Heeft er iemand tips, leesvoer, advies om dit probleem aan te pakken.

Greetz RS81

Ondertussen heb ik gewoon het ethernet shield van Arduino en kan ik pingen en server draaien. Helaas wil 1 telefoon niet reageren op een ping dus heb ik het pingen even achterwegen gelaten.

De "webserver" ben ik aan het gebruiken voor klik aan klik uit schakelaars te bedienen en wat sensordata te laten zien. Het is puur een projectje om te leren dus mogelijk komen er totaal nutteloze sensoren op.

Nu wil ik elk apparaat dat intern naar de server gaat zonder inloggen toegang geven en alle gebruikers die extern binnen komen om een wachtwoord vragen. Dit gaat op zich prima door 2x een webserver te defineren

WebServer webserver(PREFIX, 80); //Interne server
WebServer webserverExt(PREFIX, 8080); //Externe server
...
...
...

void setup()
...
...
// setup the Ehternet library to talk to the Wiznet board
Ethernet.begin(mac, ip);

// register our default command (activated with the request of
webserver.setDefaultCommand(&webCmd);
webserverExt.setDefaultCommand(&webCmd);
  /* start the server to wait for connections */
webserver.begin();
webserverExt.begin();

Omdat alle 2 de server dezelfde content moeten laten zien dacht ik met dezelfde comand (&webCmd) te werken en aan het begin van die void een check te doen vanaf welke server het verzoek komt. Ik dacht het onderstaande te doen maar dat is niet toegestaan.

void webCmd(WebServer &server, WebServer::ConnectionType type, char *, bool)
{
  if(server == webserverExt)
  {
    if (server.checkCredentials("dXNlcjp1c2Vy")) { // user:user in base64 is dXNlcjp1c2Vy
      server.httpSuccess();
...
...

Voor zover ik begrijp (en das nog niet veel) kan ik niet zien welke poort de server gebruikt. Bijvoorbeeld server.port

Hebben jullie een idee hoe ik kan zien of vergelijken vanaf welk server het verzoek kom? Ik hoop dat het een beetje duidelijk is wat ik bedoel

Greetz RS81

Ik heb wat tijd gehad om na te denken en ik zou er nog een extra functie tussen kunnen doen.

//externe command WebCmd_ext(server, connectiontype, char) autorisatie check En hier WebCmd_int aanroepen

//interne command WebCmd_int(server, connectiontype, char) standaard HTML verwerking

Siert voor de slechte lay-out maar zit het even snel via mijn telefoon te tikken.

Geerts RS81

Meerdere Pagina's?

Gewoon hetzelfde ip adres gebruiken, met daarachter een schuine streep, en de naam van je Pagina. Bijvoorbeeld 192.168.1.90/Sensor1

Gewoon het voorbeeld Webserver uit de examples pakken. De char c's achter elkaar plakken tot een nieuwe variabele. HttpHeader = HttpHeader + c En daar filter je dan de gevraagde pagina uit.

Pingen ?..... Geen idee.

Omdat ik een probleem had met te weinig geheugen bij de Nano heb ik even moeten wachten tot de Mega binnen was.

Ondertussen de boel op de Mega aan de gang.

-1 webserver draait intern (dus gewoon via elke pc/telfoon/tablet die om mijn netwerk zit te bereiken
-1 webserver draait ook voor extern. De poort van die webserver is in mijn router opengezet zodat hij via het www te bereiken is.

Het voordeel van deze keuze is dat ik intern geen wachtwoord hoeft te gebruiken en toch extern hem kan bereiken door middel van een wachtwoord.

Waarschijnlijk niet de netste oplossing maar zo doe ik het ongeveer

WebServer webserver("", 80);
WebServer webserverExt("", 8080);

....

void setup()
{
  ....
  // setup the Ehternet library to talk to the Wiznet board
  Ethernet.begin(mac, ip);

  // register our default command (activated with the request of
  webserver.setDefaultCommand(&webCmd);
  webserverExt.setDefaultCommand(&webCmd2);
  /* start the server to wait for connections */
  webserver.begin();
  webserverExt.begin();
  ....

void loop()
{
  // process incoming connections one at a time forever
  webserver.processConnection(); 
  webserverExt.processConnection(); 
}

void webCmd(WebServer &server, WebServer::ConnectionType type, char *url, bool complete)
{
  handleRequest(server, type, url, complete, false); 
}


void webCmd2(WebServer &server, WebServer::ConnectionType type, char *url, bool complete)
{
    if (server.checkCredentials("dXNlcjp1c2Vy")) { // user:user in base64 is dXNlcjp1c2Vy
      handleRequest(server, type, url, complete, true); 
    } else if (server.checkCredentials("YWRtaW46YWRtaW4=")) { // admin:admin in base64 is YWRtaW46YWRtaW4=
      handleRequest(server, type, url, complete, true);
    } else{
      server.httpUnauthorized();
    }
}

void handleRequest(WebServer &server, WebServer::ConnectionType type, char *url, bool complete, bool ext)
{
  if (type == WebServer::POST)
  {
....

Verder heb ik ontdekt dat ik nog geen moer snap van variabelen. In andere programmeertalen ging dat een stuk makkelijker. Variabelen zoals bool, long, int snap ik. Maar het char verhaal is elke keer gokken en experimenteren of het werkt. Kan iemand mij hier een beetje mee op weg helpen. Of weet er iemand een goede pagina in het Nederlands (Mijn engels is redelijk maar in NL begrijp ik het beter)

Wat ik tegenkom:
char >> 1 char
char* >> variabel in grote?
char >> krijgt het formaat van de tekst die er achter staat en is niet vergrootbaar?
char[int] >> krijgt het formaat van de int en is niet vergrootbaar?
char * >> geen idee

Als ik nu een bestand vanaf SD lees dan lees ik die char voor char en print dat op een hele lompe manier. Zie voorbeeld hieronder

while (myFile.available()) 
    {
       char dat = myFile.read();
       outputString[stringIndex] = dat; // Store it
       stringIndex++;
       if(stringIndex == 10)
       {
          stringIndex = 0;
          server << outputString[0];
          server << outputString[1];
          server << outputString[2];
          server << outputString[3];
          server << outputString[4];
          server << outputString[5];
          server << outputString[6];
          server << outputString[7];
          server << outputString[8];
          server << outputString[9];
       }
        
    }

Maar als ik nu een bepaald woord in een regel van het bestand wil lezen/zoeken/vervangen dan gaat dit natuurlijk mis.

Ik hoop dat iemand leesvoer voor me heeft zodat ik het beter kan gaan begrijpen

Groet,
RS81

char * is een pointer naar een x-aantal chars. Voordeel hiervan is dat je manipulatie kan toepassen direct in het geheugen zonder eerst de variabele binnen te hoeven halen. Een uiterst krachtig instrument en is zeer de moeite waard om te leren. Vast wel wat te vinden over 'pointers' en de taal 'C'.

Kijk met de juiste termen kom ik al verder met zoeken. Het woordje pointer miste ik.....

Het is me nog niet helemaal duidelijk maar misschien wordt het duidelijk na het experimenteren.

Nu weer wat vrije tijd zoeken....

Bedankt voor de tip

Ik heb even een stapje terug gedaan en een simpele test/leer sketch gemaakt. De char arrays heb ik nu al iets beter door. Kan de lengte bepalen, kan hem vullen en snap het afsluiten. Nu was het tijd om erin te zoeken.

De strstr functie:
Helaas is de uitkomst me niet helemaal duidelijk. Voor mijn gevoel krijg ik met de strstr functie data terug terwijl ik niks terug zou moeten krijgen.

Kan iemand een duwtje in de juiste richting geven.

Sketch

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

File myFile;
char sBuffer[150];

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");


  int index = 0;
  unsigned short int lineNumber = 1;
  // re-open the file for reading:
  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");
    
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      char c = myFile.read();
      if(c == '\n')
      {
        // Close string array
        sBuffer[index++] = '\0';
        int iLenght = strlen(sBuffer);
        Serial.print("End of line: ");
        Serial.print(lineNumber++);
        Serial.print(".Lenght is ");
        Serial.print(iLenght);
        Serial.print(" chars. Testcase: [");
        char testcase = *strstr(sBuffer, "flip-1"); 
        Serial.print(testcase);
        Serial.println("]");
        //reset buffer ??
        sBuffer[150];
        index = 0;
      }
      else
      {
        if(index == 148)
        {
          Serial.println("Buffer overflow");
        }
        else
        {
          sBuffer[index++] = c;
        }
      }
     // sBuffer[index++] = myFile.read();
      
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

void DoStuff(char[] )
{
}

void loop()
{
  // nothing happens after setup
}

Output in serial

End of line: 9.Lenght is 60 chars. Testcase: [f]
End of line: 10.Lenght is 87 chars. Testcase: [-]
End of line: 11.Lenght is 115 chars. Testcase: [-]
End of line: 12.Lenght is 59 chars. Testcase: [l]
End of line: 13.Lenght is 116 chars. Testcase: [f]
End of line: 14.Lenght is 51 chars. Testcase: [l]

De test.txt

  <body style="font-size:62.5%;" class="ui-mobile-viewport ui-overlay-a">
    <div data-role="page" class="jqm-demos ui-page ui-page-theme-a ui-page-active" data-quicklinks="true" data-url="/" tabindex="0"
    style="min-height: 755px;">
      <div role="main" class="ui-content" jqm-content="">
        <div data-demo-html="true">
          <p>Not learning</p>
          <form>
            <div class="ui-field-contain">
              <label for="flip-1">Alle verlichting:</label>
              <div class="ui-flipswitch ui-shadow-inset ui-bar-inherit ui-corner-all">
                <a href="http://192.168.178.200/#" class="ui-flipswitch-on ui-btn ui-shadow ui-btn-inherit">On</a>
                <span class="ui-flipswitch-off">Off</span>
                <select name="flip-1" id="flip-1" data-role="flipswitch" class="ui-flipswitch-input" tabindex="-1">
                  <option value="off">Off</option>
                  <option value="on">On</option>
                </select>
              </div>
              <label for="flip-2">Keuken verlichting:</label>
              <div class="ui-flipswitch ui-shadow-inset ui-bar-inherit ui-corner-all">
                <a href="http://192.168.178.200/#" class="ui-flipswitch-on ui-btn ui-shadow ui-btn-inherit">On</a>
                <span class="ui-flipswitch-off">Off</span>
                <select name="flip-2" id="flip-2" data-role="flipswitch" class="ui-flipswitch-input" tabindex="-1">
                  <option value="off">Off</option>
                  <option value="on">On</option>
                </select>
              </div>
              <label for="flip-3">Kamer verlichting (Bank):</label>
              <div class="ui-flipswitch ui-shadow-inset ui-bar-inherit ui-corner-all">
                <a href="http://192.168.178.200/#" class="ui-flipswitch-on ui-btn ui-shadow ui-btn-inherit">On</a>
                <span class="ui-flipswitch-off">Off</span>
                <select name="flip-3" id="flip-3" data-role="flipswitch" class="ui-flipswitch-input" tabindex="-1">
                  <option value="off">Off</option>
                  <option value="on">On</option>
                </select>
              </div>
              <label for="flip-4">Kamer verlichting (Kast):</label>
              <div class="ui-flipswitch ui-shadow-inset ui-bar-inherit ui-corner-all">
                <a href="http://192.168.178.200/#" class="ui-flipswitch-on ui-btn ui-shadow ui-btn-inherit">On</a>
                <span class="ui-flipswitch-off">Off</span>
                <select name="flip-4" id="flip-4" data-role="flipswitch" class="ui-flipswitch-input" tabindex="-1">
                  <option value="off">Off</option>
                  <option value="on">On</option>
                </select>
              </div>
              <label for="flip-5">Inleermodus:</label>
              <div class="ui-flipswitch ui-shadow-inset ui-bar-inherit ui-corner-all">
                <a href="http://192.168.178.200/#" class="ui-flipswitch-on ui-btn ui-shadow ui-btn-inherit">On</a>
                <span class="ui-flipswitch-off">Off</span>
                <select name="flip-5" id="flip-5" data-role="flipswitch" class="ui-flipswitch-input" tabindex="-1">
                  <option value="off">Off</option>
                  <option value="on">On</option>
                </select>
              </div>
            </div>
          </form>
        </div>
      </div>
    </div>
    <div class="ui-loader ui-corner-all ui-body-a ui-loader-default">
      <h1>loading</h1>
    </div>
  </body>

Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.

The matching process does not include the terminating null-characters, but it stops there.

dus

*strstr(sBuffer, "flip-1");

geeft een 'f' als hij de waarde gevonden heeft of de waarde die op addres 0 zit als er geen "flip-1" op de lijn staat. waarom? * geeft (in dit geval) de character weer die staat op de pointer. daar de pointer "points to the first occurrence of str2 in str1" point hij dus naar een 'f' en dus is * pointer naar 'f' een 'f'.

Met vriendelijke groet Jantje

Kort samengeval zou het dit dus moeten zijn(?): -Zoekwoord wel gevonden > Eerste teken van het zoekwoord -Zoekwoord niet gevonden > Eerste teken op adres 0

Hoe werken die adressen dan? Ik dacht dat het een vaste locatie in het geheugen was. Bij mij krijg ik elke keer een andere waarde terug van dat adres 0. Zie nieuw voorbeeld:

test.txt

1 een doos vol appels
2 een doos vol peren
3 een doos vol arduinos
4 een doos vol bananen
5 een doos vol appels
6 een doos vol peren
7 een doos vol geld
8 een doos vol arduinos
9 een doos vol appels
10 een doos vol niks

output

Initializing SD card...initialization done.
test.txt:
End of line: 1.Lenght is 22 chars. Testcase: [a]
End of line: 2.Lenght is 21 chars. Testcase: [ ]
End of line: 3.Lenght is 24 chars. Testcase: [p]
End of line: 4.Lenght is 23 chars. Testcase: [p]
End of line: 5.Lenght is 22 chars. Testcase: [a]
End of line: 6.Lenght is 21 chars. Testcase: [ ]
End of line: 7.Lenght is 20 chars. Testcase: [ ]
End of line: 8.Lenght is 24 chars. Testcase: [p]
End of line: 9.Lenght is 22 chars. Testcase: [a]

zoek deel in de sketch

 Serial.print(" chars. Testcase: [");
 char testcase = *strstr(sBuffer, "appels"); 
 Serial.print(testcase);
 Serial.println("]");

Om te weten wat op adress 0 zit zou je in de data sheet van de processor moeten kijken. Dat zou BV de huidige instructie pointer kunnen zijn en dan krijg je altijd een andere waarde.
In het kort: Ik weet niet wat je wilt bereiken maar IMHO is de code

*strstr(str1,str2);

maar heel zelden (of nooit) wat je echt wilt.
Jantje

Ik weet ook niet wat ik wil bereiken :)

Ik heb moeite met bijvoorbeeld het char deel inclusief het bewerken ervan. Ik ben dus gewoon domweg functies aan het lezen en proberen te begrijpen wat de uitkomst is. Als je niet weet wat de uitkomst is dan heb je ook niks aan de functie.

Ik ga er gewoon nog verder mee experimenteren en anders naar de volgende functie

Bedankt RS81

Vanaf welk moment worden jullie me zat??

Ben er wel achter dat het een taaie programmeertaal is. C#, PHP, LUA, Javescript vergeven je veel meer… Maar ik geef niet snel op.

Nog wat vragen: Welke bron kan ik als goede referentie aanhouden?
Ik kwam bijvoorbeeld met google in een script/sketch deze (strcasestr) functie tegen maar ik kan die in de referenties die ik gebruik niet terug vinden.

Ik ben wat verder gekomen met de strstr functie. Het zoeken naar een woord gaat nu goed. Nu dacht ik een poging te doen om iets te vervangen. De vervang functie (strncpy) crasht als je iets probeert te vervangen wat er niet instaat. Dit is vrij logisch.

Nu dacht ik naar de lengte te kijken van het zoekresultaat. Deze is 0 als er niks gevonden is en de lengte van de zoekopdracht als er wel wat gevonden is.

Nu dacht ik een IF te gebruiken om te kijken of de lengte meer dan 0 is. Op 1 of andere vage manier werkt die IF niet.

Wederom ben ik niks aan het maken maar gewoon aan het experimenteren en is de uitkomst niet volgens mijn verwachting.

Output

Initializing SD card...initialization done.
test.txt:
1 een doos vol appels

End of line: 1.Lenght is 22 chars. Testcase: [appels
]. Searchresult lenght:7. Replace functie aangeroepen
2 een doos vol peren

End of line: 2.Lenght is 21 chars. Testcase: []. Searchresult lenght:0. Replace functie aangeroepen
3 een doos vol arduinos

End of line: 3.Lenght is 24 chars. Testcase: []. Searchresult lenght:0. Replace functie aangeroepen
4 een doos vol bananen

End of line: 4.Lenght is 23 chars. Testcase: []. Searchresult lenght:0. Replace functie aangeroepen
5 een doos vol appels

End of line: 5.Lenght is 22 chars. Testcase: [appels
]. Searchresult lenght:7. Replace functie aangeroepen
6 een doos vol peren

End of line: 6.Lenght is 21 chars. Testcase: []. Searchresult lenght:0. Replace functie aangeroepen
7 een doos vol geld

End of line: 7.Lenght is 20 chars. Testcase: []. Searchresult lenght:0. Replace functie aangeroepen
8 een doos vol arduinos

End of line: 8.Lenght is 24 chars. Testcase: []. Searchresult lenght:0. Replace functie aangeroepen
9 een doos vol appels

End of line: 9.Lenght is 22 chars. Testcase: [appels
]. Searchresult lenght:7. Replace functie aangeroepen

sketch

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

File myFile;
char sBuffer[150];

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");


  int index = 0;
  unsigned short int lineNumber = 1;
  // re-open the file for reading:
  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");
    
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      char c = myFile.read();
      if(c == '\n')
      {
        // Close string array
        sBuffer[index++] = '\0';
        int iLenght = strlen(sBuffer);
        Serial.print(sBuffer);
        Serial.println("");
        Serial.print("End of line: ");
        Serial.print(lineNumber++);
        Serial.print(".Lenght is ");
        Serial.print(iLenght);
        Serial.print(" chars. Testcase: [");
       
       char searchString[] = "appels";
        char * searchResult;
        searchResult = strstr (sBuffer,searchString);
        Serial.print(searchResult);

        Serial.print("]. Searchresult lenght:");
        Serial.print(strlen(searchResult));
        short int resultInt = 0;
        //if(strlen(searchResult)+2 >= 3)
        if(strlen(searchResult) >= 1)
        {
          //strncpy (searchResult,"sample",6);
          Serial.print(". Replace functie aangeroepen");
        }
        * searchResult;
       // puts (sBuffer);
        
       
         //Serial.print(sBuffer);
         Serial.println("");
        //reset buffer ??
        sBuffer[150];
        index = 0;
      }
      else
      {
        if(index == 148)
        {
          Serial.println("Buffer overflow");
        }
        else
        {
          sBuffer[index++] = c;
        }
      }
     // sBuffer[index++] = myFile.read();
      
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

void DoStuff(char[] )
{
}

void loop()
{
  // nothing happens after setup
}

Had de FAQ nog niet gelezen :-[

http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html dit zou dus de referentie moeten zijn..