Arduino über Fremdwebseite steuern

Hallo,

da ich über die Suche nichts Konkretes zu diesem Thema finden konnte wirf ich die Frage mal in den Raum.

Ist es möglich, wenn ich mein Arduino als Webserver betreibe und über diesen diverse Relais steuere die schalter in eine fremde Webseite implementieren kann?
Oder direkt von einer anderen Seite den Server steuere?

der aufgespielte code sieht folgendermaßen aus:

#include <EtherCard.h>

#define LED1PIN 6
#define LED2PIN 7
#define LED3PIN 8
#define LED4PIN 9

#define STATIC 0 // set to 1 to disable DHCP (adjust myip/gwip values below)

#if STATIC
// ethernet interface ip address
static byte myip[] = { 192,168,1,200 };
// gateway ip address
static byte gwip[] = { 192,168,1,1 };
#endif

// ethernet mac address - must be unique on your network
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };

byte Ethernet::buffer[500]; // tcp/ip send and receive buffer
boolean led1Status;
boolean led2Status;
boolean led3Status;
boolean led4Status;

void setup () {

Serial.begin(57600);
Serial.println("WebLeds Demo");

if (ether.begin(sizeof Ethernet::buffer, mymac, 53) == 0)
Serial.println( "Failed to access Ethernet controller");
#if STATIC
ether.staticSetup(myip, gwip);
#else
if (!ether.dhcpSetup())
Serial.println("DHCP failed");
#endif

ether.printIp("IP: ", ether.myip);
ether.printIp("GW: ", ether.gwip);
ether.printIp("DNS: ", ether.dnsip);

pinMode(LED1PIN, OUTPUT);
pinMode(LED2PIN, OUTPUT);
pinMode(LED3PIN, OUTPUT);
pinMode(LED4PIN, OUTPUT);

digitalWrite(LED1PIN, LOW);
digitalWrite(LED2PIN, LOW);
digitalWrite(LED3PIN, LOW);
digitalWrite(LED4PIN, LOW);

led1Status = false;
led2Status = false;
led3Status = false;
led4Status = false;
}

void loop() {

word len = ether.packetReceive();
word pos = ether.packetLoop(len);

if(pos) {

if(strstr((char *)Ethernet::buffer + pos, "GET /led_off.png") != 0)
send_png_image(led_off, sizeof(led_off));
else if(strstr((char *)Ethernet::buffer + pos, "GET /led_on.png") != 0)
send_png_image(led_on, sizeof(led_on));

else {

if(strstr((char *)Ethernet::buffer + pos, "GET /?LED1") != 0) {
led1Status = !led1Status;
digitalWrite(LED1PIN, led1Status);
}

if(strstr((char *)Ethernet::buffer + pos, "GET /?LED2") != 0) {
led2Status = !led2Status;
digitalWrite(LED2PIN, led2Status);
}
if(strstr((char *)Ethernet::buffer + pos, "GET /?LED3") != 0) {
led3Status = !led3Status;
digitalWrite(LED3PIN, led3Status);
}
if(strstr((char *)Ethernet::buffer + pos, "GET /?LED4") != 0) {
led4Status = !led4Status;
digitalWrite(LED4PIN, led4Status);
}

BufferFiller bfill = ether.tcpOffset();
bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\nPragma: no-cache\r\n\r\n"
"WebLeds"
"Toggle leds: "));

if(led1Status) bfill.emit_p(PSTR("<a href="/?LED1"><img src="led_on.png">"));
else bfill.emit_p(PSTR("<a href="/?LED1"><img src="led_off.png">"));

if(led2Status) bfill.emit_p(PSTR("<a href="/?LED2"><img src="led_on.png">"));
else bfill.emit_p(PSTR("<a href="/?LED2"><img src="led_off.png">"));

if(led3Status) bfill.emit_p(PSTR("<a href="/?LED3"><img src="led_on.png">"));
else bfill.emit_p(PSTR("<a href="/?LED3"><img src="led_off.png">"));

if(led4Status) bfill.emit_p(PSTR("<a href="/?LED4"><img src="led_on.png">"));
else bfill.emit_p(PSTR("<a href="/?LED4"><img src="led_off.png">"));

bfill.emit_p(PSTR(""));
ether.httpServerReply(bfill.position());
}
}
}

void send_png_image(PGM_P png_image, unsigned int image_size) {

BufferFiller bfill = ether.tcpOffset();
bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\n"
"Content-Type: image/png\r\n\r\n"));
bfill.emit_raw_p(png_image, image_size);
ether.httpServerReply(bfill.position());
}

Grüße

Also du kannst den Code in beliebige Internetseiten einbinden. Nur ist es auf dem Arduino nicht möglich eine etwas kompliziertere Benutzerverwaltung einzurichten.

Besser ist es, falls schon ein Webserver irgendwo existiert, keine Internetseite auf dem Arduino zu implementieren, sondern direkt die ganze Benutzerschnittstelle auf dem Server laufen zu lassen und nur die Steuerdaten zu übertrage.

Ich nutze das zweite Beispiel nun seit längerer Zeit. Sobald ich auf die Website auf dem Server zugreife öffnet dieser eine Socket Verbindung zum Arduino und überträgt meine Eingaben. Zudem kann der Server auch eine gescheite Fehlermeldung zurückgeben, falls ein Fehler beim Verbindungsaufbau auftritt.

blueser:
Ist es möglich, wenn ich mein Arduino als Webserver betreibe und über diesen diverse Relais steuere die schalter in eine fremde Webseite implementieren kann?

Sogenannte "Frames" wurden schon kurz nach dem WWW erfunden: http://de.selfhtml.org/html/frames/definieren.htm

Und "iFrames" hat Microsoft ein paar Jahre später erfunden und funktionieren heute auch mit allen Browsern: http://de.selfhtml.org/html/frames/eingebettete.htm

Sowohl mit Frames als auch mit iFrames kannst Du auf einer Webseite quasi "eingebettete Fensterbereiche" erstellen, die von externen Webservern geliefert werden.

Vorsicht: Je nach Sicherheitseinstellungen des Webbrowsers kann das Anzeigen von Frames/iFrames von externen Quellen unterdrückt werden.

Auf der sicheren Seite bist Du eher, wenn Du z.B. per PHP den externen Arduino-Webserver abfragen würdest, um dann aus der Serverantwort eine neue Seite aufzubauen (oder diese unverändert auszuliefern), ohne dass der Besucher der Webseite mitbekommt, dass die Daten nicht von der Domain ausgeliefert werden, von der er sie anfordert.

Die zweite Variante klingt sehr interessant, nur wie schaffe ich es die Steuerdaten von der Webseite (läuft auf einer Synology) an den Arduino zu senden?

Was ich prinzipiell erreichen will ist eigentlich nur einen einfachen Schalter auf der Webseite einzubinden der mir ein Relais öffnet oder schließt jedoch ohne eigenen Webserver
auf dem Arduino.

Ich habe auch auf dem NAS einen Webserver am laufen. Die meisten unterstützen PHP.

Die PHP Code könnte dann wie folgt aussehen:

<?php 
//socket verbindung
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n"); 
socket_connect($socket, '192.168.178.50', 20108) or die("connect!");

// get parameter von der internetseite
if(isset($_GET['prog'])) 
{
    //parameter an arduino übertragen
    socket_write($socket, $_GET['prog']."\0") or die("write"); 
    //antwort abwarten, (der controller sendet ein 'ack' als bestätigung)
    $data = @socket_read($socket, 1024, PHP_NORMAL_READ); 
}

//socket schließen
socket_close($socket);

$img_min = '<img src="img/min.png" width="80" />';
$img_mm = '<img src="img/2uparrow.png" width="80" />';
$img_m  = '<img src="img/1downarrow.png" width="80" />';
$img_p  = '<img src="img/1uparrow.png" width="80" />';
$img_pp = '<img src="img/2downarrow.png" width="80" />';
$img_max = '<img src="img/max.png" width="80" />';

?>
<!DOCTYPE html> 
<html>
<head>
<meta charset='utf-8'><meta name='apple-mobile-web-app-capable' content='yes' />
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
<meta name='viewport' content='width=device-width, user-scalable=no'>
<title>Haus-Steuerung</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.css" />
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.js"></script>


<script>
function process()
{
    var url="http://us01.proxy.teleduino.org/api/1.0/328.php?k=26663120E8F8D53D76807CAC341CAB90&r=setServo&servo=0&position=" + document.getElementById("one").value;
    location.href=url;
    return false;

}
</script>
</head>
<body style="background-color: #111;">

<form id="color_change" method="post" action="">
<div data-role="fieldcontain">
	  <label for="slider_red">Rot:</label>
	  <input type="range" name="slider_red" id="slider_red" value="0" min="0" max="100" 
      onmouseup="document.forms['color_change'].submit()"/>
      <label for="slider_green">Grün:</label>
	  <input type="range" name="slider_green" id="slider_green" value="0" min="0" max="100" />
      <label for="slider_blue">Blau:</label>
	  <input type="range" name="slider_blue" id="slider_blue" value="0" min="0" max="100" />
      

      <label for="slider_dimmer">Dimmer:</label>
	  <input type="range" name="slider_dimmer" id="slider_dimmer" value="0" min="0" max="100" />
  </div>
</form>

</p>



</body>
</html>

Im Arduino kann man die Strings wie gehabt verarbeiten, du brauchst nur nicht mehr nach \GET zu filtern sondern vielleicht nach &variable_name=wert

Ob dein NAS PHP Unterstützt findest du raus wenn du eine Datei namens index.php erstellst und folgenden Inhalt einfügst:

<?php

phpinfo();

?>

Dort wird dir auch angezeigt welche Module aktive sind.

php wird unterstützt sprich diesen Beispielcode kann ich mir anzeigen lassen, jedoch ist mir die Thematik mit den Sockets doch recht unbekannt, wird hier quasi der Arduino über die IP direkt angesprochen?

Ja.

Der Arduino läuft als TCP Server. Ich glaub das ist eine Funktion die man am Arduino aktivieren kann. Ich kann dir das aber nicht genau sagen, da der Arduino bei mir über eine andere Komponente im Netzwerk hängt.

mit folgendem Code kannst du einen Socket öffnen über den du nun Daten schicken oder lesen kannst.

//socket verbindung
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n"); 
socket_connect($socket, '192.168.178.50', 20108) or die("connect!");

Mein Arduino hat die IP 192.168.178.50 und den PORT 20108. Dies musst du bei dir anpassen.

Der folgende Code überprüft ob die GET Parameter gesetzt sind. und sendet dann den Inhalt von prog an den arduino.
Der Link könnte wie folgt aussehen
http://NAS_WEBSERVER_IP/connect_arduino.php?prog=parameter1_parameter2_parameter_3
Ich habe nun den "_" Unterstrich als Trennzeichen gewählt. Auf dem Arduino trenne ich die Paramter wieder.

// get parameter von der internetseite
if(isset($_GET['prog'])) 
{
    //parameter an arduino übertragen
    socket_write($socket, $_GET['prog']."\0") or die("write"); 
    //antwort abwarten, (der controller sendet ein 'ack' als bestätigung)
    $data = @socket_read($socket, 1024, PHP_NORMAL_READ); 
}

//socket schließen
socket_close($socket);

Hier werden auch Daten vom Arduino Empfangen. Ich mache es so, dass sobald Daten angekommen sind der Arduino eine Antwort "ack" zurückschickt, und bestätigt das er die Daten erhalten hat. Die Daten werden im Moment nicht weiter ausgewertet, es diente nur zu Testzwecken.

Für die Theorie zu Sockets empfehle ich dir die Grundlagen:
Wiki: Sockets