Pages: [1]   Go Down
Author Topic: Funkschalter in Webserver einbinden  (Read 5739 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

MoinMoin,

ich habe seit einigen Wochen meinen Arduino und bin auch schon fleißig am testen.

Nun möchte ich diesen mit dem Ethernet-Shield und einem 433mHz-Sender als "Haus-Automations-Server" nutzen.
Der Webserver selbst läuft ohne Probleme und der Sender auch, aber sobald ich beide Codes verbinde, ist der Webserver nicht mehr erreichbar.

Ich schaffe es leider nicht, den Fehler zu finden, aber vielleicht könnt ihr mir dabei helfen.


Dies ist der Code vom Webserver:
http://jleopold.de/wp-content/uploads/2010/10/Arduino_Webserver.txt

Und dies der RC-Code:
Code:
/*
  Example for Intertechno outlets
 
  http://code.google.com/p/rc-switch/
*/

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup() {

  // Transmitter is connected to Arduino Pin #7 
  mySwitch.enableTransmit(7);
 
  // Optional set pulse length.
  // mySwitch.setPulseLength(320);
 
}

void loop() {

  // Switch on:
  // The first parameter represents the familycode (a, b, c, ... f)
  // The second parameter represents the group number
  // The third parameter represents the device number
  //
  // In this example it's family 'b', group #3, device #2
  mySwitch.switchOn('b', 1, 3);

  // Wait a second
  delay(1000);
 
  // Switch off
  mySwitch.switchOff('b', 1, 3);
 
  // Wait another second
  delay(1000);
 
}

Zusammengefügt habe ich beide dann so:
Code:
/*

Original Version by Poldi
modified by Katsu

the functions readString.append() and readString.contains() where replaced

*/

#include <SPI.h>  // insert by Katsu
// #include <WString.h> removed by Katsu
#include <Ethernet.h>
#include <RCSwitch.h> //NEU

RCSwitch mySwitch = RCSwitch(); //NEU

byte mac[] = { 0x54, 0x55, 0x58, 0x10, 0x00, 0x24 };  // entspricht einer MAC von 84.85.88.16.0.36
byte ip[]  = { 192, 168, 178, 222 };                  // IP-Adresse
byte gateway[] = { 192, 168, 178, 1 };                // Gateway
byte subnet[]  = { 255, 255, 255, 0 };

Server server(80);

int Pin3 = 3;
int Pin4 = 4;
int Pin5 = 5;
int Pin6 = 6;

String readString = String(100);      // string for fetching data from address
boolean Pin3ON = false;                  // Status flag
boolean Pin4ON = false;

void setup(){
Ethernet.begin(mac, ip, gateway, subnet);
server.begin();
pinMode(Pin3, OUTPUT);
pinMode(Pin4, OUTPUT);

mySwitch.enableTransmit(7); //NEU

Serial.begin(9600); }

void loop(){

// Create a client connection
Client client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();

//read char by char HTTP request
if (readString.length() < 100) {

//store characters to string
// readString.append(c);  removed by Katsu
readString = readString + c; // insert by Katsu
// very simple but it works...
}

Serial.print(c);  //output chars to serial port

if (c == '\n') {  //if HTTP request has ended

// readString.contains() replaced with readString.indexOf(val) > -1  by Katsu
// indexOf locates a character or String within another String.
// Returns the index of val within the String, or -1 if not found.
if(readString.indexOf("3=einschalten") > -1) {
 digitalWrite(Pin3, HIGH);
 mySwitch.switchOn('b', 1, 3); //NEU
 Serial.println("Pin 3 eingeschaltet!");
 Pin3ON = true;
}
if(readString.indexOf("3=ausschalten") > -1){
 digitalWrite(Pin3, LOW);
 mySwitch.switchOff('b', 1, 3); //NEU
 Serial.println("Pin 3 ausgeschaltet!");
 Pin3ON = false;
}
if(readString.indexOf("4=einschalten") > -1) {
 digitalWrite(Pin4, HIGH);
 Serial.println("Pin 4 eingeschaltet!");
 Pin4ON = true;
}
if(readString.indexOf("4=ausschalten") > -1){
 digitalWrite(Pin4, LOW);
 Serial.println("Pin 4 ausgeschaltet!");
 Pin4ON = false;
}

if(readString.indexOf("all=Alles+aus") > -1){
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 Serial.println("Alles ausgeschaltet");
 Pin3ON = false;
 Pin4ON = false;
}
//--------------------------HTML------------------------
client.println("HTTP/1.1 200 OK");

client.println("Content-Type: text/html");

client.println();

client.print("<html><head>");

client.print("<title>Arduino Webserver Poldi</title>");

client.println("</head>");

client.print("<body bgcolor='#444444'>");

//---Überschrift---
client.println("<br><hr />");

client.println("<h1><div align='center'><font color='#2076CD'>Arduino Webserver 1.0 by Poldi</font color></div></h1>");

client.println("<hr /><br>");
//---Überschrift---

//---Ausgänge schalten---
client.println("<div align='left'><font face='Verdana' color='#FFFFFF'>Ausg&auml;nge schalten:</font></div>");

client.println("<br>");

client.println("<table border='1' width='500' cellpadding='5'>");

client.println("<tr bgColor='#222222'>");

 client.println("<td bgcolor='#222222'><font face='Verdana' color='#CFCFCF' size='2'>Ausgang 3<br></font></td>");
 
 client.println("<td align='center' bgcolor='#222222'><form method=get><input type=submit name=3 value='einschalten'></form></td>");
 
 client.println("<td align='center' bgcolor='#222222'><form method=get><input type=submit name=3 value='ausschalten'></form></td>");
 
 if (Pin3ON)
   client.println("<td align='center'><font color='green' size='5'>ON");
 else
   client.println("<td align='center'><font color='#CFCFCF' size='5'>OFF");
   
client.println("</tr>");

client.println("<tr bgColor='#222222'>");

 client.println("<td bgcolor='#222222'><font face='Verdana' color='#CFCFCF' size='2'>Ausgang 4<br></font></td>");
 
 client.println("<td align='center' bgcolor='#222222'><form method=get><input type=submit name=4 value='einschalten'></form></td>");
 
 client.println("<td align='center' bgcolor='#222222'><form method=get><input type=submit name=4 value='ausschalten'></form></td>");
 
 if (Pin4ON)
   client.println("<td align='center'><font color='green' size='5'>ON");
 else
   client.println("<td align='center'><font color='#CFCFCF' size='5'>OFF");
   
client.println("</tr>");

   
client.println("</tr>");

client.println("</table>");


client.println("<br>");

client.println("<form method=get><input type=submit name=all value='Alles aus'></form>");

client.println("</body></html>");

//---Ausgänge schalten---

//clearing string for next read
readString="";

//stopping client
client.stop();
}}}}}

Die beiden "alten" Ausgänge müssen natürlich noch entfernt werden, aber daran wird es wohl kaum liegen.

Also, wer kann mir dabei weiterhelfen?

Ich nehme natürlich auch gerne einen anderen, fertigen Code für einen Webserver mit RC-Steuerung an smiley-wink


Im Voraus vielen Dank für eure Hilfe.


Gruß,
   Levi23
« Last Edit: August 26, 2011, 07:17:40 am by Levi23 » Logged

Hamburg, Germany
Offline Offline
Full Member
***
Karma: 3
Posts: 192
Hello world!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Keine Ahnung. Das Sketch (sowohl Original als auch modifiziert) verhält sich bei mir irgendwie nicht reproduzierbar komisch... vieleicht ein Speicherproblem oder so?

Probier's mal hiermit:
Code:
#include <SPI.h>
#include <Ethernet.h>
#include <RCSwitch.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,178, 222 };

Server server(80);

RCSwitch mySwitch = RCSwitch();


void setup() {
  Ethernet.begin(mac, ip);
  server.begin();
  mySwitch.enableTransmit(7);  
}

void loop() {
  
  char* command = httpServer();
  
  if (strcmp(command, "3an") == 0) {
       mySwitch.switchOn('b', 1, 3);
  } else if  (strcmp(command, "3aus") == 0) {
       mySwitch.switchOff('b', 1, 3);
  }

}

/**
 * HTML-Seite die dem Client zurückgeschickt wird.
 */
void httpResponse(Client c) {
  c.println("HTTP/1.1 200 OK");
  c.println("Content-Type: text/html");
  c.println();
  c.println("<a href=\"./?3an\">3 an</a><br>");
  c.println("<a href=\"./?3aus\">3 aus</a><br>");  
}

/**
 * Verarbeitet Client Anfragen und gibt falls vorhanden den GET Query
 * String, also alles was in der URL hinter dem ? steht, zurück
 */
char*  httpServer() {
  Client client = server.available();
  if (client) {
    char sReturnCommand[20];
    int nCommandPos=-1;
    sReturnCommand[0] = '\0';
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if ((c == '\n') || (c == ' ' && nCommandPos>-1)) {
          httpResponse(client);
          break;
        }
        if (nCommandPos>-1) {
          sReturnCommand[nCommandPos++] = c;
        }
        if (c == '?' && nCommandPos == -1) {
          nCommandPos = 0;
        }
      }
      if (nCommandPos > 18) {
          client.println("HTTP/1.1 414 Internal server error");
          client.println("Content-Type: text/plain");
          client.println();
          client.println("414 Request URI too long");
          sReturnCommand[0] = '\0';
          break;
      }
    }
    if (nCommandPos!=-1) {
      sReturnCommand[nCommandPos] = '\0';
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
    
    return sReturnCommand;
  }
  return '\0';
}
« Last Edit: August 26, 2011, 10:10:08 am by sui » Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Moin sui,

damit funktioniert es ohne Probleme.
Dann sitzt der Fehler wohl im HTML-Skript.

Ich brauche eigentlich auch nur die jetzt vorhanden Felder plus ein Statusfeld für die einzelnen Geräte.


Gruß,
   Levi23

Edit:
Ich habe nun eine gute Lösung gefunden:

Code:
#include <SPI.h>
#include <Ethernet.h>
#include <RCSwitch.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,158,222 };

Server server(80);

int rund=0;
int runh=0;
int runm=0;
int runs=0;
int Licht3=0;

unsigned long last_millis1=0;

RCSwitch mySwitch = RCSwitch();


void setup() {
  Ethernet.begin(mac, ip);
  server.begin();
  mySwitch.enableTransmit(7);   
}

void loop() {
 
  char* command = httpServer();
 
  if (strcmp(command, "3an") == 0) {
       mySwitch.switchOn('b', 1, 3);
  } else if  (strcmp(command, "3aus") == 0) {
       mySwitch.switchOff('b', 1, 3);
  }
long cur_millis;
cur_millis= millis();
  if (cur_millis-last_millis1 >=1000) {     // Für den Laufzeit zähler
    runs=runs+1;
    last_millis1=cur_millis;
  }

if (runs >= 60){
    //int mem=0;
    //mem=tempc/100;

    runm=runm+1;
    runs=0;
  }


  if (runm >= 60){
    runh=runh+1;
    runm=0;
  }
  if (runh >= 24){
    rund=rund+1;
    runh=0;
  }
 
}

/**
 * HTML-Seite die dem Client zurückgeschickt wird.
 */
void httpResponse(Client c) {
  c.println("HTTP/1.1 200 OK");
  c.println("Content-Type: text/html");
  c.println();
  c.println("<big><b>ArduinoUNO-Server</b></big>");
  c.println("<hr />");
  c.println("<u>Aktiv seit:</u><br>");
  c.println(rund);
  c.println(" Tagen ");
  c.println(runh);
  c.println(" Stunden <br>");
  c.println(runm);
  c.println(" Minuten und <br>");
  c.println(runs);
  c.println(" Sekunden.<br>");
  c.println("<p>");
  c.println("<hr />");
 
  if (Licht3 == 0){
  c.println("<a href=\"./?3an\"><button>Licht3 anschalten</button></a><br>");
  Licht3 = 1;

  }
 
  else if (Licht3 == 1){
  c.println("<a href=\"./?3aus\"><button>Licht3 ausschalten</button></a><br>"); 
  Licht3 = 0;

  }
 
 
}

/**
 * Verarbeitet Client Anfragen und gibt falls vorhanden den GET Query
 * String, also alles was in der URL hinter dem ? steht, zurück
 */
char*  httpServer() {
  Client client = server.available();
  if (client) {
    char sReturnCommand[20];
    int nCommandPos=-1;
    sReturnCommand[0] = '\0';
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if ((c == '\n') || (c == ' ' && nCommandPos>-1)) {
          httpResponse(client);
          break;
        }
        if (nCommandPos>-1) {
          sReturnCommand[nCommandPos++] = c;
        }
        if (c == '?' && nCommandPos == -1) {
          nCommandPos = 0;
        }
      }
      if (nCommandPos > 18) {
          client.println("HTTP/1.1 414 Internal server error");
          client.println("Content-Type: text/plain");
          client.println();
          client.println("414 Request URI too long");
          sReturnCommand[0] = '\0';
          break;
      }
    }
    if (nCommandPos!=-1) {
      sReturnCommand[nCommandPos] = '\0';
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
   
    return sReturnCommand;
  }
  return '\0';
}


Das wird auch auf meinem Handy ordentlich angezeigt.
Nun kommen noch mehrere zu schaltende Geräte und einige Temperatursensoren dazu und die Variablennamen werden etwas aufgeräumt.

Falls Interesse besteht, kann ich den Fortschritt gerne hier dokumentieren.

« Last Edit: August 26, 2011, 04:27:12 pm by Levi23 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nun habe ich doch ein Problem:
Wenn ich den Befehl "Licht3=0/1" direkt in den HTML-Bereich setze, wird bei jedem klicken zwar der Text im Button aktualisiert, aber dafür wechselt dieser natürlich auch beim erneuten Laden der Seite ohne klicken.

Wenn ich dann den Befehl nach oben on den "void loop" setze, ändert sich der Text zwar nicht mehr beim alleinigen Aktuallisieren, aber dafür bleibt der Text auch nach dem klicken gleich und muss durch ein Aktuallisieren der Seite erneuert werden.

Wie kann ich nun also sicherstellen, dass der Text im Button automatisch (und nur beim Klicken) neu geladen wird?

Ich denke da entweder an einen String, der in den Button kommt oder an einen Befehl an den Browser, nich zu cachen.
Beides habe ich aber bisher nicht hinbekommen.

Hier der aktuelle Code:
Code:
#include <SPI.h>
#include <Ethernet.h>
#include <RCSwitch.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,158,222 };

Server server(80);

int rund=0;
int runh=0;
int runm=0;
int runs=0;
int Licht3=0;


unsigned long last_millis1=0;

RCSwitch mySwitch = RCSwitch();


void setup() {
  Ethernet.begin(mac, ip);
  server.begin();
  mySwitch.enableTransmit(7); 
  mySwitch.switchOff('b', 1, 3);
}

void loop() {
 
  char* command = httpServer();
 
  if (strcmp(command, "3an") == 0) {
       mySwitch.switchOn('b', 1, 3);
       Licht3 = 1;


       

  } else if  (strcmp(command, "3aus") == 0) {
       mySwitch.switchOff('b', 1, 3);
       Licht3 = 0;


  }
 
long cur_millis;
cur_millis= millis();
  if (cur_millis-last_millis1 >=1000) {     // Für den Laufzeit zähler
    runs=runs+1;
    last_millis1=cur_millis;
  }

if (runs >= 60){
    //int mem=0;
    //mem=tempc/100;

    runm=runm+1;
    runs=0;
  }


  if (runm >= 60){
    runh=runh+1;
    runm=0;
  }
  if (runh >= 24){
    rund=rund+1;
    runh=0;
  }
 
 
}

/**
 * HTML-Seite die dem Client zurückgeschickt wird.
 */
void httpResponse(Client c) {
 
  c.println("HTTP/1.1 200 OK");
  c.println("Content-Type: text/html");
  c.println();
  c.println("<big><b>ArduinoUNO-Server</b></big>");
  c.println("<hr />");
  c.println("<u>Aktiv seit:</u><br>");
  c.println(rund);
  c.println(" Tagen ");
  c.println(runh);
  c.println(" Stunden <br>");
  c.println(runm);
  c.println(" Minuten und <br>");
  c.println(runs);
  c.println(" Sekunden.<br>");
  c.println("<p>");
  c.println("<hr />");
 
  if (Licht3 == 0){
  c.println("<a href=\"./?3an\"><button>Licht3 anschalten</button></a><br>");


  }
 
  else if (Licht3 == 1){
  c.println("<a href=\"./?3aus\"><button>Licht3 ausschalten</button></a><br>"); 


  }
 
 
 
 
}

/**
 * Verarbeitet Client Anfragen und gibt falls vorhanden den GET Query
 * String, also alles was in der URL hinter dem ? steht, zurück
 */
char*  httpServer() {
  Client client = server.available();
  if (client) {
    char sReturnCommand[20];
    int nCommandPos=-1;
    sReturnCommand[0] = '\0';
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if ((c == '\n') || (c == ' ' && nCommandPos>-1)) {
          httpResponse(client);
          break;
        }
        if (nCommandPos>-1) {
          sReturnCommand[nCommandPos++] = c;
        }
        if (c == '?' && nCommandPos == -1) {
          nCommandPos = 0;
        }
      }
      if (nCommandPos > 18) {
          client.println("HTTP/1.1 414 Internal server error");
          client.println("Content-Type: text/plain");
          client.println();
          client.println("414 Request URI too long");
          sReturnCommand[0] = '\0';
          break;
      }
    }
    if (nCommandPos!=-1) {
      sReturnCommand[nCommandPos] = '\0';
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
   
    return sReturnCommand;
  }
  return '\0';
}

« Last Edit: August 27, 2011, 02:31:50 am by Levi23 » Logged

Heidelberg
Offline Offline
Full Member
***
Karma: 1
Posts: 207
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo

wenn ich dass richtig übersehe arbeitest du mit Links. Das sieht alles ein wenig merkweürdig aus und fast der gesamte Code zielt auf das auslesen des query strings.

Ich fände eine bessere Lösung wäre eine html form mit einem target, welches den Beginn der main loop durchläuft.

Sobald du das frei im Internet stehen hast, wette ich : Alle 2 Sekunden wird das Licht von irgendwelchen Bots geschaltet. Da gibt es coh Beispiele hier im Forum für das auslesen eines query Strings.
Logged

 

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich habe mich ein wenig ins Thema eingelesen, aber leider ist mein HTML-Wissen noch zu gering.

Kann mir jemand vielleicht einen Beispielcode für die HTML-Form mit Tagret geben?
(mir reicht ein Button mit Text der gleich einen Wert von 0 oder 1 in eine Variable schreibt)
« Last Edit: August 28, 2011, 08:17:07 am by Levi23 » Logged

Germany
Offline Offline
Full Member
***
Karma: 1
Posts: 130
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo Levi23,

Zuhause habe ich noch ein bisschen Code, der den Arduino etwas entlastet und alle HTML-Sachen auf die SD Karte auslagert und nur minimalen Platz auf dem Ardu benötigt.
Das Ganze habe ich mit einer Art Passwortabfrage abgesichert. Das ist aber noch sehr, sehr rundimentär implementiert.
Durch das GET, wird es zum einen in reiner Form übertragen und des weiteren kann man es in der Browserzeile sehen ;-)
Zumindest schützt es vor dem Zugriff von WebCrawlern oder Technik begeisterten Freunden smiley-grin

Sieht dann in etwa so aus:
http://meinArduino:80/?aktion=pins&pin=5&pw=4711&btn=Submit
Die einzelnen Werte liest man aus und liefert den Pinstatus zurück. Das ein/ausschalten wird dann genauso gelöst und nur eine andere "Aktion" mitgeliefert.

Wen ich heute Abend dran denke, Poste ich mal die Codes.

Gruß,
trib

[Edit:] Natürlich hat sui volkommen Recht und es handelte sich in meinem Beispiel um ein GET und nicht um ein POST. Das habe ich mal angepasst.
« Last Edit: August 29, 2011, 05:52:31 am by Trib » Logged

Hamburg, Germany
Offline Offline
Full Member
***
Karma: 3
Posts: 192
Hello world!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Kleiner http Kurs:

Es gibt eine Reihe von Requestmethoden die bei Anfragen an den Webserver verwendet werden. Die bekanntesten sind GET und POST. Beide werden verwendet, um eine bestimmte Resource abzufragen, GET ist die FeldWaldundWiesen Abfrage die bei jedem angeklickten Link zu Tragen kommt. Bei POST können zusätzliche Daten im für normalsterbliche unsichtbaren HTTP-Body vom Browser an den Server übertragen werden. Mit GET kann man auch Daten übertragen, allerdings werden die Daten dann nicht im HTTP-Body sondern als Querystring (das ist alles hinter dem ?) in der URL mitgegeben. Naturgemäß sieht man die Parameter bei GET in der URL, und beim Seite neu laden werden die natürlich auch erneut an den Server gesendet. Bei POST sieht man die nicht, dafür fragen die meisten Browser beim Seite neu laden nach, ob man die Daten erneut senden möchte.


Das ganze sieht auf der http Protokoll Ebene so aus (kann man mit "telnet serverIP 80" oder putty auch ausprobieren):

GET mit URL Parameter
Code:
GET /url?foo=bar&x=y HTTP/1.0
Host: example.com


POST
Code:
POST /url HTTP/1.0
Host: example.com
Content-length: 11

foo=bar&x=y

Vorteil GET beim Arduino ist: Man muss nur die erste HTTP Anfragezeile vom Browser auswerten. Ich persönlich finde Zeichenkettenoperationen beim Arduino so ätzend, dass das ein echtes Killerargument ist smiley-wink

Kleiner html Kurs:
Bei einem Formular kann man mit dem "method" Attribut angeben, ob die Daten per GET (default wenn man keine Angabe macht) oder POST gesendet werden sollen.
Code:
<form method="POST">
  <input name="foo" value="bar">
  <input name="x" value="y">
  <input type="submit">
</form>

Nur schützt ein Formular leider nicht automatisch vor Crawlern&Bots (sonst gäbe es keinen Forum/Kommentarspam) und wenn man die Daten in der Browserzeile sehen kann handelt es sich auch definitiv um ein GET, welches sich übertragungstechnisch überhaupt nicht von einem Link http://example.com/?foo=bar&x=y unterscheidet. Also folgende zwei Snippets machen exakt die gleiche HTTP-Anfrage:

Code:
<form>
  <input type="hidden" name="foo" value="bar">
  <input type="submit">
</form>

<a href="./?foo=bar">link</a>


Um das "Seite neu Laden" Problem zu beheben wäre ein einfacher hack (ohne POST oder großartiges Crossbrowser AJAX Framework geraffel):
Code:
<script>
function load(url) {
  document.images.dummyimage.src = url + "&" + Math.random();
}
</script>
<a href="#" onClick="load('./?3aus')">Licht 3 ausschalten</a>
<img src="" width="1" height="1" border="0" name="dummyimage">

Zum Thema Sicherheit vor Bots&Co: Sinnvoll könnte natürlich eine Passwortschutz sein (Basic Authentication oder was mit Cookies), eine ganz einfache Lösung wäre z.B. die Übersichtsseite zu verstecken (http://example.com/versteckt123 ist in etwa so sicher wie eine Passwortabfrage mit dem Passwort "versteckt123" bei jeder Aktion).
Logged


Germany
Offline Offline
Full Member
***
Karma: 1
Posts: 130
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wie versprochen poste ich mal meinen Code der Webseite.
Der zieht sich einfach das Ergebnis des Webresponses und gibt daraufhin die entsprechenden AN/AUS Button aus.
Code:
<script type="text/javascript">
function WritePin(PinNo, State)
{
    document.write("<tr bgColor='#222222'><td bgcolor='#222222'><font face='Verdana' color='#CFCFCF' size='2'>Ausgang "+PinNo+"<br></font></td>");

    switch(State)
    {
      case '0':
        document.write("<td align='center' bgcolor='#222222'><input type='submit' name='pin" + PinNo + "' value='off' class='buttonOn'></td>");
        document.write("<td align='center'><font color='green' size='5'>ON</font></td>");
        break;
      case '1':
        document.write("<td align='center' bgcolor='#222222'><input type='submit' name='pin" + PinNo + "' value='on' class='buttonOff'></td>");
        document.write("<td align='center'><font color='#FF0000' size='5'>OFF</font></td>");
        break;
      default:
        document.write("<td align='center' bgcolor='#222222'><input type='button' value='Analog Input' class='buttonNone'></td>");
        document.write("<td align='center'><font color='#CFCFCF' size='5'>" + State + "</font></td>");
        break;
    }
    document.write("</tr>");
}

// new prototype defintion
document.include = function(url)
{
 var oRequest = new XMLHttpRequest();
 var sURL  = '/?pin'+url;

 oRequest.open("GET",sURL,false);
 oRequest.setRequestHeader("User-Agent",navigator.userAgent);
 oRequest.send(null)

 if (oRequest.status==200)
   {
     var txt = oRequest.responseText;
     if(txt != "")
     {
       WritePin(url,txt);
     }
     else
       document.write(txt);
   }
 else
   document.write("<td align='center'><font color='#CFCFCF' size='5'>Error executing XMLHttpRequest call! "+url+"</font></td>");
}
</script>
[...]Tabellen, Form mit GET, usw.[...]
<script>
document.include("5");
document.include("A5");
</script>

Im Ardu unterscheide ich dann natürlich zwischen "A" für Analog und nur der reinen Zahl als Digitalpin:
Code:
//Show Pins
    if(strstr(filename, "?pin") != 0)
    {
      char * thisChar;
      filename = filename + 4; //Remove "?pin"
      Serial.println(filename);
      //Pins ein/ausschalten
      if(strstr(filename, "=") != 0)
      {       
        Serial.println("Turn Pins");
        thisChar = &filename[0];
        if(filename+2 == "on")
          digitalWrite(atoi(thisChar), HIGH);
        if(filename+2 == "off")
          digitalWrite(atoi(thisChar), LOW);
        client.print(filename);
      }else{
      if(strstr(filename, "A") != 0)
      {
      //Analog Pin       
        filename = filename+1;//Remove A
        thisChar = &filename[0];
        Serial.println(thisChar);
        client.print(analogRead(atoi(thisChar)));       
      }
      else
      {       
        //DigitalPin
        thisChar = &filename[0];
        client.print(digitalRead(atoi(thisChar)));       
        Serial.println("digital Read hat geklappt");
      }
      }
    }
Hoffe das ist soweit alles recht selbst erklärend. Grundlage zum Arduino-Code ist die <Ethernet.h>

Gruß,
trib
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Vielen Dank für die Hilfe, ich bin jetzt deutlich weiter.

Ich habe nun noch zwei Probleme:

- Wenn ich den zweiten Teil der Tabelle (für das zweite Gerät) einbinde, hängt sich der Server bei Eingaben immer auf.
  Der zweite Teil alleine funktioniert aber und wenn ich zwei verschiedene Tabellen benutze, ändert sich auch nichts.
  Wo liegt der Fehler?

- Wie kann ich nun einen einfachen Passwortschutz (oder Ähnliches) einbinden?

Hier der Code:
Code:
/*

Original Version by Poldi
modified by Katsu
modified by Levi23

the functions readString.append() and readString.contains() where replaced

*/

#include <SPI.h>  // insert by Katsu
// #include <WString.h> removed by Katsu
#include <Ethernet.h>
#include <RCSwitch.h>

byte mac[] = { 0x54, 0x55, 0x58, 0x10, 0x00, 0x24 };  // entspricht einer MAC von 84.85.88.16.0.36
byte ip[]  = { 192, 168, 178, 222 };                  // IP-Adresse
byte gateway[] = { 192, 168, 178, 1};                // Gateway
byte subnet[]  = { 255, 255, 255, 0 };

Server server(80);


int rund=0;
int runh=0;
int runm=0;
int runs=0;
unsigned long last_millis1=0;


String readString = String(100);      // string for fetching data from address
boolean Funk1AN = false;                  // Status flag
boolean Funk2AN = false;                  // Status flag

RCSwitch mySwitch = RCSwitch();

void setup(){
Ethernet.begin(mac, ip, gateway, subnet);
server.begin();
mySwitch.enableTransmit(7);

}

void loop(){

long cur_millis;
cur_millis= millis();
  if (cur_millis-last_millis1 >=1000) {    // Für den Laufzeit zähler
    runs=runs+1;
    last_millis1=cur_millis;
  }
if (runs >= 60){
    //int mem=0;
    //mem=tempc/100;

    runm=runm+1;
    runs=0;
  }
  if (runm >= 60){
    runh=runh+1;
    runm=0;
  }
  if (runh >= 24){
    rund=rund+1;
    runh=0;
  }
 
  
// Create a client connection
Client client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();

//read char by char HTTP request
if (readString.length() < 100) {

//store characters to string
// readString.append(c);  removed by Katsu
readString = readString + c; // insert by Katsu
// very simple but it works...
}


if (c == '\n') {  //if HTTP request has ended

// readString.contains() replaced with readString.indexOf(val) > -1  by Katsu
// indexOf locates a character or String within another String.
// Returns the index of val within the String, or -1 if not found.

if(readString.indexOf("1=einschalten") > -1) {
 mySwitch.switchOn('c', 1, 1);
 Funk1AN = true;
}
if(readString.indexOf("1=ausschalten") > -1){
 mySwitch.switchOff('c', 1, 1);
 Funk1AN = false;
}

if(readString.indexOf("2=einschalten") > -1) {
 mySwitch.switchOn('c', 1, 2);
 Funk2AN = true;
}
if(readString.indexOf("2=ausschalten") > -1){
 mySwitch.switchOff('c', 1, 2);
 Funk2AN = false;
}



//--------------------------HTML------------------------
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();

client.print("<html><head>");
client.print("<title>Arduino Heimserver</title>");
client.print("<body bgcolor='#000000' text='#ffffff'>");

//---Überschrift---
client.println("<h1><div align='center'><font color='#ff0000'>Arduino Heimserver</font color></div></h1>");
client.println("</head>");

//---Laufzeit----
client.println("<hr />");
client.println("<u>Aktiv seit:</u><br>");
client.println(rund);
client.println(" Tagen ");
client.println(runh);
client.println(" Stunden <br>");
client.println(runm);
client.println(" Minuten und <br>");
client.println(runs);
client.println(" Sekunden.<br>");
client.println("<p>");
client.println("<hr />");
client.println("<br>");

//---Tabelle 1---
client.println("<table border='1' width='100%'>");
client.println("<TR>");
client.println("<TD COLSPAN=2 ALIGN=CENTER> <FONT SIZE='+1'>Ausgang 1:</FONT>");
client.println("</TD>");
client.println("</TR>");
client.println("<tr>");
client.println("<td ALIGN=CENTER><form method=get><input type=submit style='border:0; background-color:black; color:#cccccc;' name='1' value='einschalten'></form></td>");

 if (Funk1AN){
   client.println("<td width='30%' ALIGN=CENTER rowspan='2'><font color='green' size='+3'>AN</td>");
}
 else{
   client.println("<td width='30%' ALIGN=CENTER rowspan='2'><font color='#CFCFCF' size='+3'>AUS</td>");
}

client.println("</tr>");
client.println("<tr>");
client.println("<td ALIGN=CENTER><form method=get><input type=submit style='border:0; background-color:black; color:#cccccc;' name='1' value='ausschalten'></form></td>");
client.println("</tr>");


/*
//---Tabelle 2---
client.println("<TR>");
client.println("<TD COLSPAN=2 ALIGN=CENTER> <FONT SIZE='+1'>Ausgang 2:</FONT>");
client.println("</TD>");
client.println("</TR>");
client.println("<tr>");
client.println("<td ALIGN=CENTER><form method=get><input type=submit style='border:0; background-color:black; color:#cccccc;' name='2' value='einschalten'></form></td>");

 if (Funk2AN){
   client.println("<td width='30%' ALIGN=CENTER rowspan='2'><font color='green' size='+3'>AN</td>");
}
 else{
   client.println("<td width='30%' ALIGN=CENTER rowspan='2'><font color='#CFCFCF' size='+3'>AUS</td>");
}

client.println("</tr>");
client.println("<tr>");
client.println("<td ALIGN=CENTER><form method=get><input type=submit style='border:0; background-color:black; color:#cccccc;' name='2' value='ausschalten'></form></td>");
client.println("</tr>");
*/
client.println("</table>");


client.println("</body></html>");


//clearing string for next read
readString="";

//stopping client
client.stop();
}}}}}
« Last Edit: September 05, 2011, 08:34:38 am by Levi23 » Logged

Germany
Offline Offline
Full Member
***
Karma: 1
Posts: 130
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo Levi23,

warum sich der Ardu aufhängt weiß ich nicht genau. Da jedes Println sofort an den Client gesendet wird, sollte die Menge an HTML-Code kaum eine Rolle spielen.
Trotzdem hast du das äußerst Redundant programmiert. D.h. Tabelle1 & Tabelle2 sind nahezu identisch. Das könnte man optimaler in einer Schleife lösen.
Falls du nun noch einen weiteren Funkstecker einbauen möchtest, müsstest du nur die Schleife um einen Zähler erweitern.
(Vorausgesetzt, du lagerst FUNKAN in ein Array aus)

Genauso
Code:
if(readString.indexOf("1=ausschalten") > -1)
dort wäre es schöner, die Nummer des Schalters zu extrahieren und diese dann an die Funktion zu Übergeben. Z.B.:
Code:
if(readString.indexOf("=ausschalten") > -1)
mySwitch.switchOff('c', 1, readString[0]); //Zeichen an der ersten Position auslesen
else if(readString.indexOf("=einschalten") > -1)
  [...]

Zur Passwortsicherung:
Erweiter deine <form method=get> um ein <Input type='password' name='pw'>. Das kannst du dann genauso auslesen, wie den Ein-/Ausschalter.
Nun sollte dein readString so aussehen: "1=ausschalten&pw=DeinPasswort".
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Danke für die schnelle Antwort, Trib.

Code:
if(readString.indexOf("=ausschalten") > -1)
mySwitch.switchOff('c', 1, readString[0]); //Zeichen an der ersten Position auslesen
else if(readString.indexOf("=einschalten") > -1)
mySwitch.switchOn('c', 1, readString[0]); //Zeichen an der ersten Position auslesen

Klappt bei mir leider nicht. Vielleicht muss für die erste Zahl noch ein Dummy in das "indexOf" ?

Wobei ich ja momentan noch im "Rohbau" bin und den Server später dann etwas komprimieren werde.
Es sind aktuell auch nur drei Funkempfänger geplant, also kann man sich den längeren Code noch leisten.

Heute werde ich wohl noch ein paar Temperaturfühler hinzufügen, aber das Problem mit dem zweiten Tabellen-Teil steht ja noch im Raum.
Hoffentlich findet jemand bald den Fehler.


Wie sicher ist denn mein jetziger Code, wenn der Server über DynDNS angesprochen wird?
Könnte man nicht die Sicherheit erhöhen, ohne dass ich ein Passwort eingeben muss?
Vielleicht über ein Passwort in der Adresse der HTML-Seite? Aktuell landet man ja über den Port direkt drauf.
Einen ähnlichen Vorschlag gab es hier ja schon, aber ich habe noch nicht ganz verstanden, wie das zu programieren ist.



Gruß,
   Levi23


Edit:
Sobald ich in den HTML-Bereich ein paar Zeilen für die Temperatur-Anzeige hinzufüge, spinnt der Server bei der Weitergabe von GET-Werten wieder rum.
Dabei ist der ganze andere Kram im Setup und so völlig egal; Es liegt wahrscheinlich nur an den zusätzlichen client.println.
Aber warum?

Edit2:
Wie kann ich einen float mit zwei Nachkommastellen als Zahl mit nur einer Nachkommastelle anzeigen lassen? (bzw. wie muss ich diesen umwandeln)
Wenn ich den trennenden Punkt durch ein Komma ersetzen kann, würde mich das auch freuen.


Ich hab es mit dieser Rechnung versucht, die klappt aber nicht, da er mir dann zwei Nullen als Nachkommastellen anzeigt:
Code:
temperatur = temperatur * 10;
temperatur_NEU = (int)(temperatur + .5);
temperatur = temperatur_NEU / 10;


Edit3:
Ich verstehe das nicht: Wenn ich den Teil mit der Laufzeit rausnehme, funktioniert der Server mit der Tabelle1 und dem Temperaturen gleichzeitig.
Sind Laufzeit, Temperaturen und die Tabelle1 drinn, gibt es Fehler.
Auch bei Tabelle1 und Tabelle2 glechzeitig (alles andere aus) startet der Server nicht.
Gibt es vielleicht eine Begrenzung der client.println-Befehle?
« Last Edit: September 06, 2011, 05:37:52 am by Levi23 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich bin nun ein wenig weiter:
Wenn ich alle Tabellen raus nehme, scheint alles zusammen zu funktionieren.
Aber sobald ich bei den Schaltern auch nur einen Buchstaben oder eine Zeile zur Benennung hinzufüge, funktioniert der GET-Befehl nicht mehr oder der Server startet erst gar nicht.

Hat jemand von euch eine Ahnung, woran das liegen könnte?
Ist der vielleicht der RAM überlastet (was ich mir kaum vorstellen kann)?

Hier der aktuelle Code:
Code:
/*

Original Version by Poldi
modified by Katsu
modified by Levi23

the functions readString.append() and readString.contains() where replaced

*/

#include <SPI.h>  // insert by Katsu
// #include <WString.h> removed by Katsu
#include <Ethernet.h>
#include <RCSwitch.h>
#include <OneWire.h>
#include <DallasTemperature.h>

byte mac[] = { 0x54, 0x55, 0x58, 0x10, 0x00, 0x24 };  // entspricht einer MAC von 84.85.88.16.0.36
byte ip[]  = { 192, 168, 158, 148 };                  // IP-Adresse
byte gateway[] = { 192, 168, 158, 1 };                // Gateway
byte subnet[]  = { 255, 255, 255, 0 };

Server server(80);


int rund=0;
int runh=0;
int runm=0;
int runs=0;
unsigned long last_millis1=0;


float temp1;
float temp2;
float temp3;
long previousMillis = 0;
long interval = 1000;

String readString = String(100);      // string for fetching data from address
boolean Funk1AN = false;                  // Status flag
boolean Funk2AN = false;                  // Status flag
boolean Funk3AN = false;                  // Status flag
RCSwitch mySwitch = RCSwitch();

// Data wire is plugged into port 6 on the Arduino
#define ONE_WIRE_BUS 6
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);


void setup(){
Ethernet.begin(mac, ip, gateway, subnet);
server.begin();
mySwitch.enableTransmit(7);

mySwitch.switchOff('c', 1, 1);
mySwitch.switchOff('c', 1, 2);
mySwitch.switchOff('c', 1, 3);

}

void loop(){

//---Laufzeit---
long cur_millis;
cur_millis= millis();
  if (cur_millis-last_millis1 >=1000) {     // Für den Laufzeit zähler
    runs=runs+1;
    last_millis1=cur_millis;
  }
if (runs >= 60){
    //int mem=0;
    //mem=tempc/100;
    runm=runm+1;
    runs=0;
  }
  if (runm >= 60){
    runh=runh+1;
    runm=0;
  }
  if (runh >= 24){
    rund=rund+1;
    runh=0;
  }
 
 
//---Temperatur---
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > interval){
previousMillis = currentMillis;
sensors.requestTemperatures(); // Send the command to get temperatures
temp1 = sensors.getTempCByIndex(0); 
temp2 = sensors.getTempCByIndex(1);
temp3 = sensors.getTempCByIndex(2);
}


// Create a client connection
Client client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();

//read char by char HTTP request
if (readString.length() < 100) {

//store characters to string
// readString.append(c);  removed by Katsu
readString = readString + c; // insert by Katsu
// very simple but it works...
}


if (c == '\n') {  //if HTTP request has ended

// readString.contains() replaced with readString.indexOf(val) > -1  by Katsu
// indexOf locates a character or String within another String.
// Returns the index of val within the String, or -1 if not found.


if(readString.indexOf("1=ein") > -1) {
 mySwitch.switchOn('c', 1, 1);
 Funk1AN = true;
}
if(readString.indexOf("1=aus") > -1){
 mySwitch.switchOff('c', 1, 1);
 Funk1AN = false;
}

if(readString.indexOf("2=ein") > -1) {
 mySwitch.switchOn('c', 1, 2);
 Funk2AN = true;
}
if(readString.indexOf("2=aus") > -1){
 mySwitch.switchOff('c', 1, 2);
 Funk2AN = false;
}

if(readString.indexOf("3=ein") > -1) {
 mySwitch.switchOn('c', 1, 3);
 Funk3AN = true;
}
if(readString.indexOf("3=aus") > -1){
 mySwitch.switchOff('c', 1, 3);
 Funk3AN = false;



//--------------------------HTML------------------------
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();

client.print("<html><head>");
client.print("<title>Arduino Heimserver</title>");
client.print("<body bgcolor='#000000' text='#ffffff'>");

//---Überschrift---
client.println("<h1><div align='center'><font color='#ff0000'>Arduino Heimserver</font color></div></h1>");
client.println("</head>");

//---Laufzeit----
client.println("<hr />");
client.println("<u>Aktiv seit:</u><br>");
client.println(rund);
client.println(" Tagen ");
client.println(runh);
client.println(" Stunden <br>");
client.println(runm);
client.println(" Minuten und <br>");
client.println(runs);
client.println(" Sekunden.<br>");
client.println("<p>");
client.println("<hr />");


//---Temperatur---
client.println("<font size=-1><b>Wohnzimmer:&nbsp;</b></font>");
client.println(temp1);
client.println("&deg;C");
client.println("<br>");
client.println("<font size=-1><b>AquariumOb:&nbsp;&nbsp;&nbsp;</b></font>");
client.println(temp2);
client.println("&deg;C");
client.println("<br>");
client.println("<font size=-1><b>AquariumUn:&nbsp;&nbsp;&nbsp;</b></font>");
client.println(temp2);
client.println("&deg;C");
client.println("<p>");
client.println("<hr />");

//---Funkschalter---
client.println("<form method=get><input type=submit name=1 value=ein>&nbsp;<input type=submit name=1 value=aus>");
if (Funk1AN){
   client.println("<font color='green' size=7>AN</font></form>");
 }
 else{
   client.println("<font color='red' size=7>AUS</font></form>");
 }


client.println("<form method=get><input type=submit name=2 value=ein>&nbsp;<input type=submit name=2 value=aus>");
if (Funk2AN){
   client.println("<font color='green' size=7>AN</font></form>");
 }
 else{
   client.println("<font color='red' size=7>AUS</font></form>");
 }
 

client.println("<form method=get><input type=submit name=3 value=ein>&nbsp;<input type=submit name=3 value=aus>");
if (Funk3AN){
   client.println("<font color='green' size=7>AN</font></form>");
 }
 else{
   client.println("<font color='red' size=7>AUS</font></form>");
 }


client.println("</body></html>");


//clearing string for next read
readString="";

//stopping client
client.stop();
}}}}}
Logged

Pages: [1]   Go Up
Jump to: