Forum: Mikrocontroller und Digitale Elektronik PCs über WOL mit Arduino einschalten


von heinzz (Gast)


Lesenswert?

hallo,

ich möchte zwei PCs mit meinem Arduino Uno übers LAN starten lassen.

Die PCs sprechen beide über WOL an, ich kann diese über die FritzBox 
einwandfrei starten.
Wenn ich Sie aber über den Arduino starten lasse, startet nur ein PC.
Warum?

Hier der Code:
1
#include <SPI.h>
2
#include <Ethernet.h>
3
#include <EthernetUdp.h>
4
5
// ETHERNET CONFIGURATION
6
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xB1, 0xAC }; // Arduino's MAC address
7
byte ip[] = { 192, 168, 178, 21 }; // Arduino IP address
8
byte gw[] = { 192, 168, 178, 1}; // Gateway IP address
9
byte bc[] = { 192, 168, 178, 255 }; // Broadcast IP address
10
11
// WOL CONFIGURATION
12
byte pc_mac[] = {0x--, 0x--, 0x--, 0x--, 0x--, 0x--}; //PC startet nicht
13
byte pc_mac_2[] = {0x--, 0x--, 0x--, 0x--, 0x--, 0x-- }; //Startet schon
14
15
EthernetUDP Udp;
16
17
char WOL_done = 0;
18
19
void setup() {
20
    Ethernet.begin(mac,ip,gw);
21
    delay(100);
22
    Udp.begin(7);
23
    delay(100);
24
}
25
26
void WOL(byte mac[]) {
27
    byte preamble[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
28
    char i;
29
30
    Udp.beginPacket(bc, 7);
31
    Udp.write(preamble, sizeof preamble);
32
    
33
    for (i=0; i<16; i++)
34
      Udp.write(mac, 6);
35
    
36
    Udp.endPacket();
37
}
38
39
void loop() {
40
  if (! WOL_done)
41
    WOL(pc_mac);
42
    WOL(pc_mac_2);
43
  WOL_done = 1;
44
}

von Bitflüsterer (Gast)


Lesenswert?

Wenn man schon den selben Code wie alle anderen verwendet, warum dann 
nicht auch die selbe Suchmaschine?

Beitrag "Arduino als WOL server"

von heinzz (Gast)


Lesenswert?

Den Code habe ich ja verwendet. Funktioniert aber trotzdem nicht :-(

von Frank (Gast)


Lesenswert?

Hm ... ohne jetzt tiefer in den Code eingestiegen zu sein, muss da 
irgendwas fehlen. Vlt. solltest du dich mal mit dem Prinzip von WOL 
vertraut machen.

- eine schlafende Netzwerkkarte hat keine IP-Adresse, man muss die 
WOL-Pakete per Broadcast ins Netz blasen, egal ob TCP oder UDP

- innerhalb der "magic packet" muss die MAC-Adresse der Netzwerkkarte 
des zu weckenden PC enthalten sein

Beides kann ich in dem obenstehenden Code nicht sehen. Ich habe hier mal 
etwas BASIC-Code (RealBasic für Mac, funktioniert 100%ig), vlt. kannst 
du den lesen und adaptieren:
1
  dim usock as UDPSocket
2
  dim macbin, mac16, pref as string
3
  dim i as integer
4
  
5
  macbin="00f83d2200de" //mac address without extra chars, no ':' or '-'
6
  mac16=""
7
  pref=""
8
  
9
  for i= 1 to 6
10
    macbin = macbin + ChrB(val("&h"+nthfield(macadr, ":", i)))
11
  next
12
  
13
  for i=1 to 6
14
    pref = pref + chrB(&hFF)
15
  next
16
  
17
  for i=1 to 16
18
    mac16 = mac16 +macbin
19
  next
20
  
21
  usock = new UDPSocket
22
  if usock<>nil then
23
    usock.port = 3307
24
    usock.connect
25
    usock.write usock.BroadcastAddress, pref + mac16
26
    usock.close
27
  end if

von Frank (Gast)


Lesenswert?

Nachtrag: Broadcast-Adresse ist "hinten" mit 255, also z.B. 
192.168.178.255

von Frank (Gast)


Lesenswert?

noch ein Nachtrag: Im obenstehenden Code muss muss die Mac-Adresse DOCH 
mit ':' angegeben werden. In der For-Schleife darunter werden die 
einzelnen Bytes separiert ...

von heinzz (Gast)


Lesenswert?

kann deinen Code nicht lesen.
Mein Code muss ja funktionieren. Ein PC von zwei startet doch.

von heinzz (Gast)


Lesenswert?

Also, ich habe gerade mal die mac adressen der zwei PCs in meinem 
Programm getauscht.
Jetzt startet der PC der zuvor nicht startete und der PC der startete 
startet nichtmehr ^^

von asterix (Gast)


Lesenswert?

heinzz schrieb:
> Mein Code muss ja funktionieren. Ein PC von zwei startet doch.

geniale Fehleranalyse ! :-D

von Marcus W. (marcusaw)


Lesenswert?

Mach doch mal beim "if (!WOL_done) " geschweifte klammern ran - und 
lerne verdammt nochmal selbst zu programmieren, statt bloß 
abzuschreiben.

von heinzz (Gast)


Lesenswert?

danke, habe ich übersehen. Funktioniert aber immernoch nicht :-(
1
 
2
3
// Arduino Wake-On-LAN
4
// Needs Arduino > 1.0-beta3 with the new UDP API ( http://code.google.com/p/arduino/wiki/Arduino1 )
5
6
// Date: 04 September 2011
7
// Author: Michele Spagnuolo
8
// Email: michele@spagnuolo.me
9
// Site: http://michele.spagnuolo.me
10
11
#include <SPI.h>
12
#include <Ethernet.h>
13
#include <EthernetUdp.h>
14
15
// ETHERNET CONFIGURATION
16
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xB1, 0xAC }; // Arduino's MAC address
17
byte ip[] = { 192, 168, 178, 21 }; // Arduino IP address
18
byte gw[] = { 192, 168, 178, 1}; // Gateway IP address
19
byte bc[] = { 192, 168, 178, 255 }; // Broadcast IP address
20
21
// WOL CONFIGURATION
22
byte pc_mac[] = {0x00, 0x--, 0x--, 0x--, 0x--, 0x--}; // PC's MAC address
23
byte pc_mac_2[] = {0x--, 0x--, 0x--, 0x--, 0xC4, 0x-- }; // 2. PC's MAC
24
25
EthernetUDP Udp;
26
27
char WOL_done = 0;
28
29
void setup() {
30
    Ethernet.begin(mac,ip,gw);
31
    delay(100);
32
    Udp.begin(7);
33
    delay(100);
34
}
35
36
void WOL(byte mac[]) {
37
    byte preamble[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
38
    char i;
39
40
    Udp.beginPacket(bc, 7);
41
    Udp.write(preamble, sizeof preamble);
42
    
43
    for (i=0; i<16; i++)
44
      Udp.write(mac, 6);
45
    
46
    Udp.endPacket();
47
}
48
49
void loop() {
50
  if (! WOL_done)
51
  {
52
    WOL(pc_mac);
53
    WOL(pc_mac_2);
54
    WOL_done = 1;
55
  }
56
}

von Sönke P. (snke_p)


Lesenswert?

Ich nehme mal an, dass pc_mac_2 der startende PC war, da für diesen 
aufgrund der fehlenden Klammer keine if-Bedingung galt und das WOL-Paket 
somit in jedem Schleifenlauf gesendet wurde.

Also mal probieren, WOL() mehrfach für beide PCs auszuführen.
Z.B.
1
void loop() {
2
  if  (WOL_done == 0) {
3
    for (WOL_done=0; WOL_done<10; WOL_done++) {
4
      WOL(pc_mac);
5
      WOL(pc_mac_2);
6
  }
7
}

: Bearbeitet durch User
von heinzz (Gast)


Lesenswert?

Sönke Peters schrieb:
> Ich nehme mal an, dass pc_mac_2 der startende PC war, da für
> diesen
Richtig.

Leider funktioniert es mit deinem Beispiel auch nicht.

von Cyblord -. (cyblord)


Lesenswert?

heinzz schrieb:
> Sönke Peters schrieb:
>> Ich nehme mal an, dass pc_mac_2 der startende PC war, da für
>> diesen
> Richtig.
>
> Leider funktioniert es mit deinem Beispiel auch nicht.

Mal Wireshark angeworfen und geschaut was da genau gesendet wird und ob 
sich WOL 1 von WOL2 irgendwie unterscheidet?

Oder lass es und werd Gärtner. Wer Code abtippt (auch noch falsch), nix 
selber kann und wenns dann nicht sofort geht, doof dreinschaut und 
keinerlei Debugging betreiben will oder kann, der sollte es einfach 
lassen.

von Jochen S. (jochen_s)


Lesenswert?

Hallo,

ist es richtig, dass immer nur der PC startet, der als zweites 
angesprochen wird? Falls ja, würde ich mal tippen, dass es am Anfang zu 
schnell geht und deshalb die erst angesprochenen Netzwerkkarte nicht 
reagiert. Versuche mal vorher noch eine "DUMMY" WOL durchzuführen, oder 
die erste Karte zweimal zu wecken. Eventuell ein Timingproblem?


Jochen

von heinzz (Gast)


Lesenswert?

ne geht auch nicht

Jochen S. schrieb:
> Hallo,
>
> ist es richtig, dass immer nur der PC startet, der als zweites
> angesprochen wird? Falls ja, würde ich mal tippen, dass es am Anfang zu
> schnell geht und deshalb die erst angesprochenen Netzwerkkarte nicht
> reagiert. Versuche mal vorher noch eine "DUMMY" WOL durchzuführen, oder
> die erste Karte zweimal zu wecken. Eventuell ein Timingproblem?
>
> Jochen

geht leider auch nicht.

von Cyblord -. (cyblord)


Lesenswert?

Ich möchte nochmal Wireshark einwerfen. Poste mal ein Dump der beiden 
Pakete.

von Daniel A. (daniel-a)


Lesenswert?

Vileicht geht es wenn du zwichen den WOL ein delay einbaust. Das wäre 
dann aber nicht die Lösung, sondern nur ein workarround.
1
void loop() {
2
  if (! WOL_done)
3
  {
4
    WOL(pc_mac);
5
    delay(100);
6
    WOL(pc_mac_2);
7
    WOL_done = 1;
8
  }
9
}

Wenn das funktioniert ist es vermutlich ein timingproblem.

von Cyblord -. (cyblord)


Lesenswert?

Daniel A. schrieb:
> Vileicht geht es wenn du zwichen den WOL ein delay einbaust. Das wäre
> dann aber nicht die Lösung, sondern nur ein workarround.

Oder vielleicht um Mitternacht nochmal probieren und vorher nen Hahn 
schlachten.
Lieber blindes rumgestocher und trial&error statt mal zielführende 
Fehlersuche.

von Marcus W. (marcusaw)


Lesenswert?

cyblord ---- schrieb:
> Oder vielleicht um Mitternacht nochmal probieren und vorher nen Hahn
> schlachten.

YMMD!

von heinzz (Gast)


Lesenswert?

alles klar, nur welche informationen aus Wireshark braucht ihr?
Ich komm mit dem Programm null klar

von Kaj (Gast)


Lesenswert?

Was mir mal direkt auffällt:
heinzz schrieb:
> char WOL_done = 0;
> ...
> void loop() {
>   if (! WOL_done)
>     WOL(pc_mac);
>     WOL(pc_mac_2);
>   WOL_done = 1;
> }

Es ist nur WOL(pc_mac) vom if(...) betroffen, nicht aber WOL(pc_mac_2), 
weil die { } bei dem if fehlen. vom Prinziep steht da halt:
1
void loop()
2
{
3
  if(! WOL_done)
4
  {
5
    WOL(pc_mac);
6
  }
7
  WOL(pc_mac_2);
8
  WOL_done = 1;
9
}
Das heißt WOL(pc_mac) wir maximal ein einziges mal ausgeführt, wenn das 
nicht klappt, naja, dann hat es halt nicht geklappt und wird nie wieder 
aufgerufen.

Es sollte wohl eher
1
void loop()
2
{
3
  if(! WOL_done)
4
  {
5
    WOL(pc_mac);
6
    WOL(pc_mac_2);
7
  }
8
  WOL_done = 1;
9
}
heißen. Wo genau du da jetzt dein WOL_done = 1 hin sortieren musst, 
überlasse ich dir. Denn in dem if-Block oder hinter dem if-Block hat 
beides den selben effekt: der if-Block wird nur einmal aufgerufen, dann 
nie wieder, und wenn das WOL bei einmaligem aufrufen nicht geklappt hat, 
naja, dann haste halt pech gehabt.

von Axel S. (a-za-z0-9)


Lesenswert?

heinzz schrieb:
> Die PCs sprechen beide über WOL an, ich kann diese über die FritzBox
> einwandfrei starten.
> Wenn ich Sie aber über den Arduino starten lasse, startet nur ein PC.
> Warum?

Offensichtlich macht die Fritzbox etwas anderes als der Arduino. Das 
könnte z.B. daran liegen, daß WOL kein Standard ist, sondern nur ein 
"Standard". Soll heißen daß jeder Hersteller sein eigenes Süppchen kocht 
und daß was auf einem System funktioniert, nicht notwendig auch auf dem 
anderen funktionieren muß.

Ich könnte mir gut vorstellen, daß die Fritzbox mehrere WOL Methoden 
implementiert (nicht nur das magic packet von oben).

Wirf also den Netzwerk-Sniffer an (Wireshark oder womit auch immer du 
klar kommst) und analysiere, was die Fritzbox sendet. Sieh es als 
Chance, etwas über Ethernet und IP zu lernen.


XL

von Cyblord -. (cyblord)


Lesenswert?

heinzz schrieb:
> alles klar, nur welche informationen aus Wireshark braucht ihr?
> Ich komm mit dem Programm null klar

GRMPF wer großartig fürs Netzwerk entwickeln will, der sollte mit 
Netzwerk-Sniffern klarkommen. Wireshark zeichnet einfach den 
Netzwerkverkehr auf und zeigt dir alle Infos zu jedem Paket an (inkl. 
Aufdröselung aller Schichten darin).
Als 1. Musst du aber sicherstellen, das dein WOL Paket überhaupt bei 
deinem sniffenden PC ankommt. Ein Switch leitet das Paket anhand seiner 
MAC Zieladresse nur aus dem Port raus, wo auch das Zielgerät häng (wenn 
der Switch die MAC Adresse bereits gelernt hat). In diesem Fall einfach 
WOL-Sender direkt an Netzwerkkarte von sniffendem PC ran. Alternative: 
Managed Switch wo man einen Port als "Monitoring" einstellen kann oder 
dummen Hub nutzen.

Dann kannst du in Wireshark z.B. nach Protokoll filtern oder nach Ziel 
bzw. Absender MAC-Adresse. Du kannst sogar direkt nach WOL Paketen 
filtern. Ja und dann schaust dir mal an OB da 2 WOL Pakete rausgehen und 
WAS da drin steht (Ziel-MAC Adresse korrekt, Inhalt korrekt usw.)

Und ICH will gar keine Infos aus Wireshark. Aber ich sage, wenn man Zeug 
fürs Netzwerk programmiert, dann ist es sehr sinnvoll, zu schauen OB und 
WAS aus meinem Gerät denn wirklich ins Netzwerk raus geht. Alles andere 
ist im Fehlerfall nämlich Kaffeesatzlesen.

Und JA, Grundlagen im Bereich Netzwerk (d.h. die wichtigsten Protokolle 
und Schichten) sollten schon da sein. Dann wird auch Wireshark auf 
einmal logisch.

gruß cyblord

: Bearbeitet durch User
von X2 (Gast)


Lesenswert?

cyblord ---- schrieb:
> Als 1. Musst du aber sicherstellen, das dein WOL Paket überhaupt bei
> deinem sniffenden PC ankommt. Ein Switch leitet das Paket anhand seiner
> MAC Zieladresse nur aus dem Port raus, wo auch das Zielgerät häng (wenn
> der Switch die MAC Adresse bereits gelernt hat). In diesem Fall einfach
> WOL-Sender direkt an Netzwerkkarte von sniffendem PC ran. Alternative:
> Managed Switch wo man einen Port als "Monitoring" einstellen kann oder
> dummen Hub nutzen.

Dürfte in diesem Fall ja egal sein, da das WOL-Paket ja eine Broadcast 
Nachricht ist.

von t_k (Gast)


Lesenswert?

heinzz schrieb:
> Also, ich habe gerade mal die mac adressen der zwei PCs in meinem
> Programm getauscht. Jetzt startet der PC der zuvor nicht startete und
> der PC der startete startet nichtmehr ^^

Na dann! einfach einen zweiten Arduino aufstellen und jeweils anders 
konfigurieren - fertsch.

von Cyblord -. (cyblord)


Lesenswert?

X2 schrieb:

> Dürfte in diesem Fall ja egal sein, da das WOL-Paket ja eine Broadcast
> Nachricht ist.

War auch eher als allgemeiner Tip gedacht. Aber auch WOL kann und wird 
meist direkt an die Ziel-MAC Adressiert. Die ist ja bekannt.

gruß cyblord

von Kassiopeia (Gast)


Lesenswert?

Zunächst einmal den Code ausräumen:

Warum wird in setup() ein Udp.begin(7) aufgerufen?  Du willst Doch nicht 
selbst UDP-Pakete empfangen?  Unter Umständen kommt hier der TCP-Stack 
des Shields durcheinander, wenn er eigene Pakete empfängt, die nicht 
verarbeitet werden?

Das Einzige, was in setup() aufgerufen werden muss, ist 
Ethernet.begin(...)!

Wo kommt die MAC des Arduino-Shields her? Ist die im Netzwerk wirklich 
eindeutig?
Sind die MAC-Adressen der Empfänger eindeutig?
Ggf. Ethernet.begin(..) inkl. Subnet-Mask aufrufen, ggf. ist der 
ARP-Resolver des Shields unsauber.  Leider gibt es da keinen Zugriff 
drauf.

Weiterhin ggf. auch mal den UDP-Zielport 9 auswählen, dieser ist meiner 
Kenntnis nach sogar weiter verbreitet.

http://wiki.wireshark.org/WakeOnLAN

Und dann ruhig die Pakete mal im Endlos-Loop schicken, begrenzen kannst 
Du dann immer noch.

Um das sinnvoll zu debuggen, kann ein Linux-Rechner mit an den Switch, 
der KEINE IP-Adresse auf dem Interface gebunden hat, das im WOL-LAN 
hängt. Darauf dann einen "tcpdump -i interface-name -s0 -w 
dateiname.cap" laufen lassen, das Ganze dann in Wireshark ansehen.

Es muss sichergestellt sein, dass der Arduino die MAC-Adresse des 
Testrechners NICHT in seinem ARP-Cache hat.  Ggf. ist die 
Implementierung des Sendens an die Broadcast-Adresse im Shield daneben 
und sendet nur an MAC-Adressen, die im ARP-Cache sind.   Das solltest Du 
aber dann im Dump sehen!

Ich würde das Programm zunächst mal so abändern:
1
#include <SPI.h>
2
#include <Ethernet.h>
3
#include <EthernetUdp.h>
4
5
// ETHERNET CONFIGURATION
6
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xB1, 0xAC }; // Arduino's MAC address
7
byte ip[] = { 192, 168, 178, 21 };  // Arduino IP address
8
byte gw[] = { 192, 168, 178, 1};    // Gateway IP address
9
byte bc[] = { 192, 168, 178, 255 }; // Broadcast IP address
10
byte nm[] = { 255, 255, 255, 0 };   // Netmask
11
12
// WOL CONFIGURATION
13
byte pc_mac[] = {0x--, 0x--, 0x--, 0x--, 0x--, 0x--}; //PC startet nicht
14
byte pc_mac_2[] = {0x--, 0x--, 0x--, 0x--, 0x--, 0x-- }; //Startet schon
15
16
EthernetUDP Udp;
17
18
char WOL_done = 0;
19
20
void setup() {
21
    Ethernet.begin(mac,ip,gw,gw,nm); //(mac, ip, dns, gateway, subnet)
22
}
23
24
void WOL(byte destPort, byte mac[]) {
25
    byte preamble[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
26
    char i;
27
    Udp.beginPacket(bc, destPort);
28
    // magic paket starts with 6 times FF
29
    Udp.write(preamble, sizeof preamble);
30
    // followed by 16 times the MAC of the destination NIC
31
    for (i=0; i<16; i++) {
32
      Udp.write(mac, 6);
33
    }  
34
    Udp.endPacket();
35
}
36
37
void loop() {
38
    WOL(7, pc_mac);
39
    WOL(7, pc_mac_2);
40
    WOL(9, pc_mac);
41
    WOL(9, pc_mac_2);
42
}

von heinzz (Gast)


Lesenswert?

Danke, aus welchem Grund auch immer funktioniert es jetzt :D
1
 
2
3
// Arduino Wake-On-LAN
4
// Needs Arduino > 1.0-beta3 with the new UDP API ( http://code.google.com/p/arduino/wiki/Arduino1 )
5
6
// Date: 04 September 2011
7
// Author: Michele Spagnuolo
8
// Email: michele@spagnuolo.me
9
// Site: http://michele.spagnuolo.me
10
11
#include <SPI.h>
12
#include <Ethernet.h>
13
#include <EthernetUdp.h>
14
15
// ETHERNET CONFIGURATION
16
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xB1, 0xAC }; // Arduino's MAC address
17
byte ip[] = { 192, 168, 178, 21 }; // Arduino IP address
18
byte gw[] = { 192, 168, 178, 1}; // Gateway IP address
19
byte bc[] = { 192, 168, 178, 255 }; // Broadcast IP address
20
21
// WOL CONFIGURATION
22
byte pc_mac_2[] = {0x--, 0x--, 0x--, 0x--, 0x--, 0x--}; // PC's MAC address
23
byte pc_mac[] = {0x--, 0x--, 0x--, 0x--, 0x--, 0x-- }; // 2. PC's MAC
24
25
EthernetUDP Udp;
26
27
char WOL_done = 0;
28
29
void setup() {
30
    Ethernet.begin(mac,ip,gw);
31
    delay(100);
32
    Udp.begin(7);
33
    delay(100);
34
}
35
36
void WOL(byte mac[]) {
37
    byte preamble[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
38
    char i;
39
40
    Udp.beginPacket(bc, 7);
41
    Udp.write(preamble, sizeof preamble);
42
    
43
    for (i=0; i<16; i++)
44
      Udp.write(mac, 6);
45
    
46
    Udp.endPacket();
47
}
48
49
void loop() {
50
  if (! WOL_done)
51
  {
52
    WOL(pc_mac);
53
    WOL(pc_mac_2);
54
    WOL_done = 1;
55
  }
56
}

von heinzz (Gast)


Lesenswert?

Oder auch nicht :-(
hat einmal funktioniert. jetzt geht nichtsmehr.
Warum?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.