Die Frage ist zwar schon was länger her, als Arduino-Neuling bin ich erst jetzt auf den Thread aufmerksam geworden und stelle mal meine Bastelarbeit vor:
Als „proof-of-concept“ einer „eierlegende Arduino-Ethernet Wollmilchsau“ habe ich einen Sketch für einen HTTP-Server und HTTP-Client auf einen Arduino Ethernet geschoben. Es ist als Versuchsbeispiel für eine eigene „HTTP-API“ bzw. zum Ansteuern jedes anderen Servers mit HTTP-API und PUT-Befehlen (wie z.B. die Mobotix-Kameras oder eben eine Web-Server-Instanz in IP-Symcon)
Im Beispiel habe ich ein Modellbau-Servo, einen Taster und 3 Dallas 1-Wire Temperatur-Sensoren angeschlossen.
Je nach aufgerufener Seite und PUT-Parametern kann das Servo verfahren werden, Taster/Schalter-Position oder Temperaturen ausgelesen werden oder durch Seitenaufruf oder Taster-Ereignis wiederum ein anderer WEB-Server aufgerufen werden - was das Pollen spart.
/*
Proof of concept "HTTP-API" Web Server und Client
Beispiel:
WEB-SERVER: - per HTTP-GET Aufruf:
Drei 1-Wire Temp. Sensoren Auslesen
Die 1-Wire Temp. Sensoren periodisch mit Browser auslesen
Alle angeschlossenen 1-Wire Adressen auslesen
Taster/Schalterposition auslesen
Einen Servo in die per PUT übergebene Position (0-180°) fahren
WEB-CLIENT:
ereignisgesteuert einen HTTP-Server mit erignisabhängiger Parameterübergabe von HTTP-Seite und PUT
Ereignisse werden im LOOP-Teil des Sketches abgefragt oder
durch Seitenaufruf auf dem SERVER ausgelöst
*/
#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Servo.h>
Servo myservo; // Servo Objekt
int svo; // Sollwert (0-180) für den anzufahrenden Servowinkel
// 1-Wire an PIN 3:
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
// Dallas Temperatur - Sensoren:
DallasTemperature sensors(&oneWire);
// Adressen der Temp-Sensoren
DeviceAddress aThermo = { 0x10, 0x3C, 0x7F, 0xAD, 0x02, 0x08, 0x00, 0x64 };
DeviceAddress bThermo = { 0x10, 0x41, 0x1E, 0xAD, 0x02, 0x08, 0x00, 0x6A };
DeviceAddress cThermo = { 0x10, 0x27, 0xD6, 0xAD, 0x02, 0x08, 0x00, 0x07 };
float tempC; // Variable zur Zwischenspeicherung der Temperaturen
String stringOne; // Variable zum extrahieren der GET-Parameter eines HTTP-Aufrufes
// MAC Addresse und IP Addresse des Arduino HTTP-Servers hier eingeben:
byte mac[] = { 0xDE, 0xDE, 0xBF, 0xEF, 0xEE, 0xED };
IPAddress ip(192,168,2,22);
EthernetServer server(80); // Port 80
// HTTP-Client:
EthernetClient httpclx;
char hpserver[] = "192.168.2.124"; // IP-Adresse des HTTP-Servers, der vom Arduino-Client aufgerufen wird
// Taster/Schalter an PIN 5
int pushButton = 5; // Taster oder Schalter an PIN 5
int buttonAlt = 1; // letzter Status des Schalters ( 0 oder 1)
unsigned long previousMillis; // Variable zur Zeitmessung für die Software-Tasterentprelllung
void setup() {
// HTTP Server starten:
Ethernet.begin(mac, ip);
server.begin();
// 1-Wire-Temp.Sensoren
sensors.begin();
// Auflösung auf 10 bit setzen
sensors.setResolution(aThermo, 10);
sensors.setResolution(bThermo, 10);
sensors.setResolution(cThermo, 10);
myservo.attach(7); // Das Servo ist an pin 7 angeschlossen
pinMode(pushButton, INPUT_PULLUP); // internen Pull-Up-Widerstand für den Taster verwenden
}
// ***** Auslesen der Adressen der angeschlossenen 1-Wire-Geräte und Ausgabe an den HTTP-Server
void discoverOneWireDevices(EthernetClient clx) {
byte i;
byte present = 0;
byte data[12];
byte addr[8];
clx.print("1-Wire Adressen werden ausgelesen....<br>");
while(oneWire.search(addr)) {
clx.print("<p>\'1-Wire\' mit der Adresse: ");
for( i = 0; i < 8; i++) {
clx.print("0x");
if (addr[i] < 16) {
clx.print('0');
}
clx.print(addr[i], HEX);
if (i < 7) {
clx.print(", ");
}
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
clx.print("CRC falsch!!!<br>");
return;
}
}
clx.print("<p>fertig<br>");
oneWire.reset_search();
return;
}
// ****** Temperatursensor auslesen und über HTTP-Server ausgeben
void printTemperature(DeviceAddress deviceAddress, EthernetClient clx)
{
float tempi = sensors.getTempC(deviceAddress);
if (tempi == -127.00) {
clx.print("Error getting temperature");
} else {
clx.print(": ");
clx.print(tempi);
}
//clx.print("<br />");
}
// **** HTTP-GET Aufruf
void httpRequest(EthernetClient sender, String seite) {
// if there's a successful connection:
if (sender.connect(hpserver, 8081)) {
sender.println(seite);
sender.println("Host: www.arduino.cc");
sender.println("User-Agent: arduino-ethernet");
sender.println("Connection: close");
sender.println();
sender.stop();
}
else {
sender.stop();
}
}
void loop() {
// Tastaturabfrage bearbeiten und wenn Taste gedrückt wurde Seite auf anderen HTTP-Server aufrufen
int buttonState = digitalRead(pushButton);
unsigned long currentMillis = millis();
if (buttonState==0) { // Taster gedrückt
if (buttonAlt==1) {
// nur bei wechsel auf 0 httprequest aufrufen
httpRequest(httpclx, "GET /lichter_schalten.php?id=48 HTTP/1.1"); // z.B. die Seite lichter_schalten.php mit dem PUT Parameter
// id=48 aufrufen
}
buttonAlt=0;
previousMillis = millis();
}else{ // Zur Tastenentprellung kann erst nach 0,5 sekunden ein nochmaliges Drücken registriert werden
if(currentMillis - previousMillis > 500) {
buttonAlt = 1;
}
}
// Wird unser HTTP-Server aufgerufen ????:
EthernetClient client = server.available();
if (client) {
boolean currentLineIsBlank = true;
String buffer = "";
while (client.connected()) {
if (client.available()) {
char c = client.read();
buffer+=c;
// In buffer steht der ankommende HTTP-GET-Header
if (c == '
' && currentLineIsBlank) {
// Üblicher Response-Header zurückschicken
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
if (buffer.indexOf("GET /t.php")>=0) {
// wenngewünscht, eine Meta-Refresh, damit der Browser periodisch eine Seite mit z.B. Messwerten aufruft
client.println("<meta http-equiv=\"refresh\" content=\"3\">");
}
if(buffer.indexOf("GET /a.php")>=0) { // wenn die Seite a.php aufgerufen wurde
client.print("Mögliche Seitennaufrufe a.php, t.php, w.php, nr.php?a=9999 oder irgendeine andere Seite");
// 1-Wire Adressen werden angezeigt
discoverOneWireDevices(client);
}else if(buffer.indexOf("GET /w.php")>=0) { // wenn w.php aufgerufen wurde
client.println("Die Anfrage wurde weitergeleitet");
httpRequest(httpclx, "GET /lichter_schalten.php?id=48 HTTP/1.1");
}else if(buffer.indexOf("GET /pin.php")>=0) {
client.print("Status PIN 5: ");
client.print(buttonState);
}else if(buffer.indexOf("GET /nr.php")>=0) { // mit /nr.php?a=0000 bis 9999 wird das Servo gesteuert
// Werte kleiner 0 oder größer 180 werden gekappt
stringOne=buffer.substring(14,18);
svo=stringOne.toInt();
// nur werte von 0-180 an das Servo
svo = min(svo, 180);
svo = max(svo, 0);
client.print("Servo auf ");
client.print(svo);
myservo.write(svo);
}else{
// Anzeige der Temperaturen , falls ein anderer Seitenname verwendet wurde
sensors.requestTemperatures();
client.println("Sensor A ");
printTemperature(aThermo,client);
client.println("<br /> Sensor B ");
printTemperature(bThermo,client);
client.println("<br /> Sensor C ");
printTemperature(cThermo,client);
}
buffer="";
client.println("</html>");
break;
}
if (c == '
') {
currentLineIsBlank = true;
}
else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
delay(1);
Schliessen der Verbindung:
client.stop();
}
}
Jetzt bin ich noch auf der Sucher nach einer Möglichkeit, den Arduino über das Ethernet mit neuen/geänderten Sketchen zu versorgen.
Rolf